Changing How a Composite Object Gets Created
In both our book and on this blog, Chandima and I have tried to clarify and simplify ActionScript 3.0 Design Patterns and yet keep them accurate and, whenever possible, practical. After reviewing many, many Builder examples, I was surprised to find pieces missing in several instances, and while the examples may have combined elements (such as the Client and Director); others simply left out crucial components. (Who could forget bad, bad Leroy Brown who looked like a jigsaw puzzle with a couple of pieces gone?)
Given this state of affairs, it occurred to me that this pattern might be tricky; however, after working up an example, it turns out to be relatively simple and useful. Nevertheless, it’s not quite as simple as some, such as the Strategy or Factory Method, and so the discussion of the Builder is in two parts. This first part provides a clear overview so that you can easily see how the different components work together and starts a practical project., The second part (in a separate post) removes the abstract trace statements and displays actual content on the stage in a useful way. This will be to see if video, SWF, text, and images can be usefully integrated using the Builder.
Builder Overview
When you first look at the Builder class diagram shown in Figure 1, you might think it looks a lot like the Strategy pattern. Well, the class diagrams are similar, but the intent is very different. Also, you’ll find that the little Product class is hugely important.

Figure 1: Builder Class Diagram
The GoF summarize the intent of the Builder class as, [to] separate the construction of a complex object from its representation so that the same construction process can create different representations. Therein lies the problem. You can imagine the different ways this may play out. One way, which we’ve used in this initial example, is to use the Product class as a general clearinghouse for products with everything going to the same Product class. It “assembles” the results of the different operations from the concrete Builder classes and displays them. Another way to use the Product class is to create a different product class for each concrete Builder class. This latter technique is good when you want to use the Builder design pattern for building products based on the same interface but generating very different results.
In one creative Builder written in Java, the developer had a single Product class and then delegated the production to different concrete classes using aggregation from the Product class to the “helper” classes. It was an interesting design in that the differences between the concrete Builder classes was minor but each had a common task that required a hefty amount of work. The solution, at first glance, seemed to be to create a separate Product class for each of the concrete Builder classes (as did GoF in one of their examples) but since the building work is not done in the Product class, he needed to add the helper classes.
To get a better picture of the Builder design pattern, the following shows the task performed by each participant in a project that builds different vacations. Each vacation shows a hotel, a major sight (e.g., Eiffel Tower), an event (e.g., Carnival) worth seeing in the selected location, and a general write-up.
Builder: The Builder is the abstract interface. In this first example, I used an interface rather than an abstract class. The operations in the Builder are the required tasks for building the different parts of the Product object. In this example, the main tasks are:
- buildHotel
- buildSight
- buildEvent
- buildWriteUp
I used the getResult() name that GoF show in the Class diagram as part of a ConcreteBuilder, but since the requests in the Client are typed to the interface (IBuilder), I needed to place it in the Builder itself.
ConcreteBuilder: Each ConcreteBuilder class implements the operations in the Builder interface, builds the product and delivers the assembled results to the Product. As noted, the getResult() retrieves the product. Because in this example, all concrete builders use the same product, it uses the same retrieval operation. However, if each built significantly different products, each of the retrieval operations would have to be unique.
Director: Using the Builder interface, the Director constructs the desired object. For example, the following are two used in our example:
builder.buildHotel();
builder.buildSight();
The Director holds an aggregate relation to the IBuilder using an IBuilder instance in a function’s parameter.
Product: The Product class is used to represent the building process. In this example, it does so by pushing elements into a Vector (or Array) object. It may include classes that define the constituent parts for assembling the parts into the final result. So you can either have multiple ConcreteBuilders instantiate the same Product object or different ones.
Composing Video, SWF, Images, and Text
In developing this application, I was thinking of a travel site that would include the following:
- An SWF file showing a hotel
- A graphic file showing a building or other sight
- A video of an event
- Text write-up describing the vacation destination
In Part II of this post I plan to fill in the current trace statements with the above objects. Because every vacation location will have each of the objects, I cannot see using separate Product classes for each of the vacation sites; therefore, it will have a similar structure as this current example.
A Builder Vacation Site
In order to provide a visual image of what this particular design pattern does, Figure 2 shows the user interface along with the output via trace statements. (If you use Kuler, either the one built into Flash CS4 or at the Adobe Kuler site, you will be happy to know that they have a color theme named Builder that has been employed in the example.)

Figure 2: Builder example with UI, background and output
The four output lines generated by selecting one of the buttons conforms to the four Builder functions (less the getResult() method). With Figure 2 in mind, we can now dissect the program.
The Client
The Client class is not shown in the class diagram, and so we need to consider where it directs its requests. According to GoF, the client creates the Director object and configures it with the desired Builder object. You will see this operation in the following format:
director.construct(trip1);
srilanka = trip1.getResult(); //srilanka = Product instance
srilanka.disclose();
The director is a Director instance and trip1 is a Builder instance typed to the IBuilder interface. In this implementation, each “trip” refers to one of the three vacation destinations—Sri Lanka, San Francisco or Prague. When one of the UI buttons is pressed, an event handler simply generates the necessary output through the Director’s construct() method. Then, a Product instance, named after the vacation destination, is assigned the return value of the particular ConcreteBuilder and then the Product disclose() method displays the information as a trace output.
The following code shows the entire Client listing:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | //Client package { import flash.display.Sprite; import fl.controls.Button; import flash.events.MouseEvent; public class Client extends Sprite { private var director:Director = new Director(); //Concrete builders private var trip1:IBuilder = new ConcreteBuilder1(); private var trip2:IBuilder = new ConcreteBuilder2(); private var trip3:IBuilder = new ConcreteBuilder3(); //Products private var srilanka:Product; private var sanfrancisco:Product; private var prague:Product; //Buttons private var btn1:Button=new Button(); private var btn2:Button=new Button(); private var btn3:Button=new Button(); public function Client() { setButtons(); } private function setButtons():void { btn1.x = 16; btn1.y = 64; btn1.label = "Sri Lanka"; btn1.addEventListener(MouseEvent.CLICK, goSriLanka); addChild(btn1); btn2.x = 16; btn2.y = 96; btn2.label = "San Francisco"; btn2.addEventListener(MouseEvent.CLICK, goSanFrancisco); addChild(btn2); btn3.x = 16; btn3.y = 128; btn3.label = "Prague"; btn3.addEventListener(MouseEvent.CLICK, goPrague); addChild(btn3); } private function goSriLanka(e:MouseEvent):void { director.construct(trip1); srilanka = trip1.getResult(); srilanka.disclose(); } private function goSanFrancisco(e:MouseEvent):void { director.construct(trip2); sanfrancisco = trip2.getResult(); sanfrancisco.disclose(); } private function goPrague(e:MouseEvent):void { director.construct(trip3); prague = trip3.getResult(); prague.disclose(); } } } |
Now that you can see the request structure, we can look at the main participants in the pattern.
Director
The Director class is a concrete class with the responsibility of constructing an object. Using its sole method construct() it uses a Builder (IBuilder) reference to create the necessary parts that make up the product.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //Director package { public class Director { public function construct(builder:IBuilder):void { builder.buildHotel(); builder.buildSight(); builder.buildEvent(); builder.buildWriteUp(); } } } |
The Director acts to create an aggregate relationship with the Builder interface (IBuilder) and allows the Client to request a product be built. In this way it maintains a loose relationship between its request and the concrete builders. This reduces dependencies thereby providing less problems changing or adding concrete builders and the products they build.
Builder Interface
I always feel more comfortable using ActionScript 3.0 interfaces than the ersatz abstract classes even though I sometimes miss the advantages of abstract classes. However, for this example, the ActionScript 3.0 interface statement is just what I need. Like most interfaces, all the IBuilder interface does is to provide abstract operations to be used in implementations. In the case of the Builder design pattern, these operations specify which parts of the Product will be built.
1 2 3 4 5 6 7 8 9 10 11 12 | //Builder Interface package { interface IBuilder { function buildHotel():void; function buildSight():void; function buildEvent():void; function buildWriteUp():void; function getResult():Product; } } |
As noted, the pattern’s class diagram does not show the getResult() method in the Builder interface , but it is necessary if the Client types to the Builder (IBuilder) interface.
Concrete Builders: The Patterns Payoff
Once the Builder interface has been established, adding or changing the concrete part builders is a piece of cake. For example, I could add as many concrete builders for different vacation destinations as I want. Likewise, I could change the parts to be “assembled” in any of the concrete builder classes. In this particular example, it’s even easier because the only thing that has to be changed is the content in the Product.assemble() operation. The following make up the three concrete builders:
Sri Lanka
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | //ConcreteBuilder1 package { public class ConcreteBuilder1 implements IBuilder { private var product:Product = new Product(); public function buildHotel():void { product.assemble("Mt. Lavinia Hotel is right on the beach"); } public function buildSight():void { product.assemble("The Temple of Buddha's tooth in Kandy is beautiful"); } public function buildEvent():void { product.assemble("Esala Perahera fesitval features elephants"); } public function buildWriteUp():void { product.assemble("Let me tell you about Sri Lanka..."); } public function getResult():Product { return product; } } } |
San Francisco
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | //ConcreteBuilder2 package { public class ConcreteBuilder2 implements IBuilder { private var product:Product = new Product(); public function buildHotel():void { product.assemble("Fairmont Hotel is a landmark in San Francisco"); } public function buildSight():void { product.assemble("Take a drive across Golden Gate Bridge"); } public function buildEvent():void { product.assemble("Don't miss the Carnival in May"); } public function buildWriteUp():void { product.assemble("Let me tell you about San Francisco..."); } public function getResult():Product { return product; } } } |
Prague
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | //ConcreteBuilder3 package { public class ConcreteBuilder3 implements IBuilder { private var product:Product = new Product(); public function buildHotel():void { product.assemble("Hotel Tyl -- small but nice"); } public function buildSight():void { product.assemble("Visit the medieval Prague Castle"); } public function buildEvent():void { product.assemble("The Prague International Jazz Festival is a treat"); } public function buildWriteUp():void { product.assemble("Let me tell you about Prague..."); } public function getResult():Product { return product; } } } |
With the parts assembly completed, we turn next to the final product—the Product Class.
Product
As we’ve discussed, the Product class represents the assembled parts created by the builders. In this example, all of the parts are pushed as strings onto a Vector object (or Array). Then the final product is displayed through a disclose() method that sends the output using a trace statement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | //Product package { public class Product { private var features:Vector.<String> = new Vector.<String>(); //If your version of Flex or Flash does not have Vector uncomment //the following line and comment out the Vector line //private var features:Array=new Array(); public function assemble(aspect:String ):void { features.push(aspect); } public function disclose():void { for each (var facet:String in features) { trace(facet); } trace(""); features.length=0; } } } |
Keeping in mind that the purpose of this first example is to see how the participants in a Builder work together, think of ways that this pattern could be applied to some of your own projects.
The Test is in Changing and Adding
This sample application ought to be a good one for changing and adding classes. Try adding another class for another city or country. You’ll have to make adjustments to the Client as well to select anything new that you add. Changing content in this particular application is simply a matter of changing the content of the text literals in the ConcreteBuilder classes.
As always, your comments and ideas are welcomed.

The ActionScript 3.0 Builder Design Pattern Part I: Controlling Creation by William B. Sanders, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.

Bill Sanders
Thanks for doing a write up on this. For whatever reason, this pattern has somehow always eluded me.
What tips do you have for building complex composition of objects, where classes contain other classes. Using your example above, what if the buildHotel() method needed to create a Hotel object? Would that method contain another builder to create the hotel for the product? Or would that be a poor approach?
Looking forward to the sequel… ps. It would be nice if we could read all the code examples without scrolling horizontally.
Hi Dan,
Given what changes (how a composite object gets created), it was a bit trickier than most; and so it’s not a surprise the Builder was elusive to you. (Took us a while too–it’s the last design pattern that Chandiam and I covered in ActionScript 3.0–on the blog and in the book.)
Where classes contain other classes, we’re dealing with tight coupling and that’s going to be a problem throughout. I think you probably mean where classes contain interfaces from other classes. Also, the Builder has aggregate relations between the Director and Builder, and it seems that the Client has aggregate relations with just about every other class! So, I would not worry about dealing with classes containing other classes if you mean they hold a common interface. Keep in mind that you don’t want to subclass a concrete class — remember the Liskov Substitution principle. Use those Lunch Bucket principles to help keep you out of trouble. (I certainly have to.)
So to answer your question, work with those 10 principles. What would they suggest? Then, when you work out your solution send it to us!! However, not to leave you hanging, you can have as many Product classes as you have concrete builders. So consider what type of product you want and build a Product class for that product. I just used one Product class, but it makes perfect sense to have as many as you have products to build. (In their example, GoF has 3 product classes.)
Kindest regards,
Bill
Hi David,
It may be a while before I can get to Part II of the Builder because I have a new client who is going to keep me busy with a custom streaming Flash Media Server video project. (Of course I plan to use Design Patterns!)
As for listings that you need not scroll, just click the upper left corner View Code hot spot of the listing and a new window opens with all of the code nice and spread out. I don’t like listings that you have to scroll either!!
Cheers,
Bill
The Builder pattern would be simpler to implement if the director and builder were combined into one class. What advantages do we gain by keeping them separate?
Hi Nambu,
We’re not going for simpler building. We’re going for simpler maintenance. By removing the Director what do you do? You tighten the coupling! We’ve been talking about that all the time on this blog. If you take shortcuts, you pay for it in the long run. Take a look at the principle of Loose Coupling and the post on Tight and Loose Programmers. Remember; we’re not worried about running out of silicon. We’re worried about taking way too many resources, time and bug by tight coupling.
Kindest regards,
Bill