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:
  1. >
  2.     tag='car'>
  3.         >My first post>
  4.     >
  5.     tag='dog'>
  6.         >What's up?>
  7.     >
  8.     tag='house'>
  9.         >The story continues...>
  10.     >
  11. >

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.

Actionscript:
  1. package {
  2.     import flash.display.Sprite;
  3.  
  4.     public class Main extends Sprite {
  5.  
  6.         private var xmlParser:FeedParser;    // Xml Parser
  7.         private var articleListBuilder:ArticleListBuilder = new ArticleListBuilder();   // Concrete Builder
  8.         private var tagCloudBuilder:TagCloudBuilder = new TagCloudBuilder();    // Concrete Builder
  9.                
  10.         public function Main() {
  11.             getMyArticles();
  12.             getMyTagCloud();
  13.         }
  14.  
  15.  
  16.         private function getMyArticles():void {
  17.             // Initialize the parser with XML data and the concrete builder
  18.             xmlParser = new FeedParser(getXmlData(), articleListBuilder);
  19.            
  20.             // start parsing
  21.             xmlParser.parse();
  22.            
  23.             // get the ArticleListe object from the builder
  24.             var myArticleList:ArticleList = articleListBuilder.getArticleList();
  25.            
  26.             // just trace it...
  27.             trace(myArticleList.getCurrentArticles());     
  28.         }
  29.  
  30.  
  31.         private function getMyTagCloud() : void {
  32.             // Initialize the parser with XML data and the concrete builder
  33.             xmlParser = new FeedParser(getXmlData(), tagCloudBuilder);
  34.            
  35.             // start parsing
  36.             xmlParser.parse();
  37.            
  38.             // get the TagCloud object from the builder
  39.             var myTagCloud:TagCloud = tagCloudBuilder.getTagCloud();
  40.            
  41.             // just trace it...
  42.             trace(myTagCloud.getCurrentTags());    
  43.         }
  44.  
  45.         // Just setup some dummy xml data
  46.         private function getXmlData():XML {
  47.         var xmlString:String =
  48.             "My first postWhat's up?The story continues...";   
  49.             return new XML(xmlString);     
  50.         }
  51.     }
  52. }

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.

Actionscript:
  1. package {
  2.  
  3.     /**
  4.      * The parser knows the XML structure and submits the data to the builder
  5.      */
  6.     public class FeedParser {
  7.        
  8.         private var xmlData:XML;
  9.         private var builder:IXmlBuilder;
  10.        
  11.         public function FeedParser(xml:XML, builderObj:IXmlBuilder) {
  12.             xmlData = xml;      // save the data
  13.             builder = builderObj;   // save the data
  14.         }
  15.  
  16.         public function parse():void {
  17.             // loop through the items in the xml data
  18.             for each (var node:XML in xmlData.item) {
  19.                
  20.                 // call the builder with the value from xml
  21.                 builder.buildHeadline(node.headline.text() );
  22.                
  23.                 // call the builder with the value from xml
  24.                 builder.buildTag(node.@tag);
  25.             }
  26.    
  27.         }
  28.     }
  29. }

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.

Actionscript:
  1. package {
  2.  
  3.     /**
  4.      * This Builder receives the data and creates the article list
  5.      */
  6.     public class ArticleListBuilder implements IXmlBuilder {
  7.        
  8.         private var _articleList:ArticleList = new ArticleList();
  9.        
  10.         public function buildHeadline(text:String):void {
  11.             _articleList.addArticle(text);
  12.         }
  13.        
  14.         public function buildTag(text:String):void {           
  15.         }
  16.        
  17.         public function getArticleList():ArticleList {         
  18.             return _articleList;   
  19.         }
  20.     }
  21. }

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?