Bei der Lektüre von Flash Engineering bin ich auf das Erzeugungsmuster „Erbauer (Builder)” gestoßen. Dieses Erzeugungsmuster ist dazu gedacht, einem bei der Erstellung von Objekten zu helfen.
Da das Pattern z.B. für das Parsen von XML-Daten äußerst hilfreich zu sein scheint, habe ich eine Beispiel dazu erstellt. Die Theorie erspare ich mir, siehe dazu z.B. Erbauer Entwurfsmuster (Wikipedia) oder ActionScript 3.0 Builder Design Pattern Part I: Controlling Creation
Ausgangslage
Als Ausgangslage habe ich XML-Daten (z.B. einen RSS-Feed).
[xml]
[/xml]
Aus diesen Daten sollen nun konkrete Objekte (eine Artikelliste und eine Tagcloud) erzeugt werden. Die Idee des Patterns liegt darin, diese Aufgabe in zwei Teilen zu trennen:
- das Parsen der XML-Daten
- das Erzeugen der Objekte
Der Vorteil: Ändern sich die XML-Daten, müsste nur der Parser angepasst werden. Würden sich die Objekte ändern oder werden neue Objekte gewünscht, ist lediglich eine Anpassung im Erzeuger (Builder) bzw. ein neuer Erzeuger notwendig.
Hauptklasse (Client)
Die Hauptklasse ruft den FeedParser
auf. Neben den XML-Daten wird ein konkreter Erzeuger übermittelt (z.B. articleListBuilder
), der das gewünschte Objekt bauen soll.
[as]
package {
import flash.display.Sprite;
public class Main extends Sprite {
private var xmlParser:FeedParser; // Xml Parser
private var articleListBuilder:ArticleListBuilder = new ArticleListBuilder(); // Concrete Builder
private var tagCloudBuilder:TagCloudBuilder = new TagCloudBuilder(); // Concrete Builder
public function Main() {
getMyArticles();
getMyTagCloud();
}
private function getMyArticles():void {
// Initialize the parser with XML data and the concrete builder
xmlParser = new FeedParser(getXmlData(), articleListBuilder);
// start parsing
xmlParser.parse();
// get the ArticleListe object from the builder
var myArticleList:ArticleList = articleListBuilder.getArticleList();
// just trace it…
trace(myArticleList.getCurrentArticles());
}
private function getMyTagCloud() : void {
// Initialize the parser with XML data and the concrete builder
xmlParser = new FeedParser(getXmlData(), tagCloudBuilder);
// start parsing
xmlParser.parse();
// get the TagCloud object from the builder
var myTagCloud:TagCloud = tagCloudBuilder.getTagCloud();
// just trace it…
trace(myTagCloud.getCurrentTags());
}
// Just setup some dummy xml data
private function getXmlData():XML {
var xmlString:String =
„
return new XML(xmlString);
}
}
}
[/as]
Feed parsen
Der Parser (allgemein Direktor genannt im Erzeuger-Pattern) kennt die XML-Struktur und liest die Werte lediglich aus. Diese werden an den Erzeuger „in Rohform“ übergeben.
[as]
package {
/**
* The parser knows the XML structure and submits the data to the builder
*/
public class FeedParser {
private var xmlData:XML;
private var builder:IXmlBuilder;
public function FeedParser(xml:XML, builderObj:IXmlBuilder) {
xmlData = xml; // save the data
builder = builderObj; // save the data
}
public function parse():void {
// loop through the items in the xml data
for each (var node:XML in xmlData.item) {
// call the builder with the value from xml
builder.buildHeadline(node.headline.text() );
// call the builder with the value from xml
builder.buildTag(node.@tag);
}
}
}
}
[/as]
Objekt erzeugen (Builder)
Mit den Daten vom Parser erstellt der Builder das tatsächlich Objekt (in diesem Fall die Artikelliste).
Wichtig: Er implementiert ein Interface (IXmlBuilder
). Dieses Interface legt quasi fest, welche Informationen der Parser in den XML-Daten erkennen kann.
[as]
package {
/**
* This Builder receives the data and creates the article list
*/
public class ArticleListBuilder implements IXmlBuilder {
private var _articleList:ArticleList = new ArticleList();
public function buildHeadline(text:String):void {
_articleList.addArticle(text);
}
public function buildTag(text:String):void {
}
public function getArticleList():ArticleList {
return _articleList;
}
}
}
[/as]
Nach dem nun das Objekt erstellt wurde, kann man aus dem Klienten die Artikelliste mit articleListBuilder.getArticleList();
abholen.
Quellcode
Den Quellcode des Projekts gibt es hier zum Download: Sourcecode (.zip)
Noch Verbesserungsvorschläge oder Anmerkungen?
[ad]