Recently on this blog I created a little application to be used for a quick lookup of the different principles used in both OOP and Design Patterns—The Lunch Bucket Rules. The app uses a Strategy design pattern that is both simple and practical. The pattern is designed to load external SWF and graphic files (.gif, .png, and .jpg) and nothing more. You can pop it on a USB drive and put it on your keychain, and you’ll have a simple design pattern that you can take to work and use whenever you want. If you need a simple design pattern starting point, this should do the trick. (You can download the whole thing, including source code and swf files if you like.)
Swiss Army Knife of Design Patterns: The Strategy Pattern
The Strategy pattern defines a family of algorithms, encapsulates each and makes them interchangeable. Figure 1 shows the basic look of the Strategy pattern:

Figure 1: Strategy pattern Class Diagram
An interface (Strategy) describes the abstract signatures for the algorithm to be used with a family of algorithms. The key here is understanding that when developing a Strategy pattern that you need to think through the implications of the abstract methods you’ve got as part of a cluster of related algorithms. Given that this example only has a single Concrete Strategy class, you can assume that you have an opportunity to add more concrete strategies, and at the end of the post I’ll suggest a few.
The Strategy and Its Subclasses
In developing projects using design patterns, you can start in a lot of different places, and I seem to have started in all of them. For this one, I started with the Client and imagined what I wanted to request. Keeping in mind that the only reason a Client should change is to make a request.
The Client is the gimme class.
Once figuring out what I wanted by fiddling around with the Client, I decided on the Strategy pattern. All I needed just for this particular application was for it to load an SWF file. However, I was thinking, what if I wanted to load materials from XML or text files? I’d have to use slightly different algorithms but different enough for different concrete strategies. So, the Strategy pattern looked to be a good place to add algorithms for loading XML and text files if somewhere down the road I wanted more flexibility in what I could load.
So first off, let’s look at the Strategy interface (an abstract class in this case) and then look at the concrete class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //Abstract class: Strategy Interface package { import flash.display.Sprite; import flash.errors.IllegalOperationError; public class ILoadMaster extends Sprite { public function loadStuff(url:String):void { throw new IllegalOperationError("Abstract method: must be overridden in a subclass"); } } } |
As you can see it’s got a single abstract method with a single string parameter. The string parameter is for the name (URL if you wish) of the file to be loaded. The implementation of this abstract class loads a SWF or graphic files.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //Concrete Strategy package { import flash.net.URLRequest; import flash.display.Loader; class PixLoader extends ILoadMaster { private var urlReq:URLRequest; private var loader:Loader; override public function loadStuff(url:String):void { urlReq = new URLRequest(url); loader=new Loader(); loader.load(urlReq); addChild(loader); } } } |
The string parameter is passed to the URLRequest class initializer, which in turn is used in the load() parameter. All in all it’s pretty simple, but it resides in a loose pattern and is easy to extend.
The Simple Beauty of the Context Class
In most of the Strategy patterns I’ve written, the Context class has subclasses. If you peruse the Web, you’ll find lots of examples of the Strategy pattern using multiple Context subclasses. (In our book this was the case and in one of the blog posts as well.) In retrospect, the Context class left in its original concrete form has much to offer. It’s like a polymorphism machine. The following Context class follows the GoF model (as does the class diagram in Figure 1).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | //Context class package { import flash.display.Sprite; public class Context extends Sprite { private var lm:ILoadMaster; public function Context(lm:ILoadMaster):void { this.lm = lm; } public function doLoad(url:String):void { lm.loadStuff(url); addChild(lm); } } } |
Even though the Context class is concrete, everything about it is abstract. The references are to ILoadMaster (the Strategy interface) and an unnamed string parameter. So you could add as many concrete strategies as you want, and they could all pass though the Context class without a concrete reference at all.
The Client Requests a Context
Finally, the Client requests whatever it wants. The Client makes a request through the Context class by instantiating an ILoadMaster instance in the instantiation process. The line,
contextDy=new Context(new PixLoader());
(in the seeNow() method), sends the request to the concrete strategy class. The Context passes the request on to the concrete strategy without knowing what concrete strategy is being requested. As long as the correct format is observed, the Context is perfectly happy.
Keeping in mind that you can make the requests any way you want the following shows how the requests were made using a List component in the version I did. However, go ahead and use any request mechanism you want.
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 | //Client class package { import flash.display.Sprite; import fl.controls.List; import fl.data.DataProvider; import fl.events.ListEvent; public class Client extends Sprite { private var context:Context=new Context(new PixLoader()); private var contextDy:Context; private var list:List; private var lunchBucket:DataProvider; private var swf:String; private var container:Sprite=new Sprite(); public function Client() { setMenu(); context.doLoad("swf/p0.swf"); container.x=180,context.y=0; container.addChildAt(context,0); addChild(container); } private function setMenu():void { lunchBucket=new DataProvider(); lunchBucket.addItem( { label: "Liskov Substitution", data:"p1.swf" } ); lunchBucket.addItem( { label: "Program to Interface", data:"p2.swf" } ); lunchBucket.addItem( { label: "Favor Composition", data:"p3.swf" } ); lunchBucket.addItem( { label: "Encapsulate What Varies", data:"p4.swf" } ); lunchBucket.addItem( { label: "Loosely Coupled Objects", data:"p5.swf" } ); lunchBucket.addItem( { label: "Open/Closed", data:"p6.swf" } ); lunchBucket.addItem( { label: "Dependency Inversion", data:"p7.swf" } ); lunchBucket.addItem( { label: "Least Knowledge Principle",data:"p8.swf" } ); lunchBucket.addItem( { label: "Hollywood Principle",data:"p9.swf" } ); lunchBucket.addItem( { label: "Only 1 Reason to Change",data:"p10.swf" } ); list=new List(); list.setSize(150,200); list.x = 16,list.y = 64; list.dataProvider = lunchBucket; addChild(list); list.addEventListener(ListEvent.ITEM_CLICK,seeNow); } private function seeNow(e:ListEvent):void { container.removeChildAt(0); contextDy=new Context(new PixLoader()); swf="swf/"+e.item.data; contextDy.doLoad(swf); container.addChildAt(contextDy,0); } } } |
You will need a folder named “swf” for the SWF files and use the naming convention shown in the lunchBucket DataProvider. (Of course, you can use any naming convention you want; just change the code in the DataProvider if you do so.) Also, if you’re using Flash, you’ll need a copy of the List component in the Library.
You’re On Your Own
The purpose of this little design pattern is to make it simple yet practical. Take it to work and see if it comes in handy when you have a project loading external files. The family of algorithms I had in mind when I decided to use this pattern is the one of loadable external data such as data from XML or text files. I believe that this pattern will do the job.
I would be delighted to see extensions of more concrete strategies using this pattern. Also I think it’s probably a good exercise for learning more about design patterns in ActionScript 3.0. Of course if you’d like to make any artful graphic improvements to my efforts, those would be a delight as well.

The ActionScript 3.0 Easy and Practical Strategy Design Pattern by William B. Sanders, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.
Related posts:

Bill Sanders
Hi Bill,
Great tutorial! Simple, elegant and useful. It makes the Strategy Pattern crystal clear.
I have coded a little silly extension to load txt files and will be using it in a project I’m currently working on.
Thank you!
Curro
Here’s the extension:
Hi Curro,
I tried your addition–works beautifully! It was even easier than I thought, and I told everyone how easy it was. All I had to do was change 2 lines in the Client, add a TextArea component to the Library and put in a folder named ‘text’ and add a text file to the folder. Here are the two client lines I changed:
private var context:Context=new Context(new PixLoader());
to
private var context:Context=new Context(new TextLoader());
—
context.doLoad(”swf/p0.swf”);
to
context.doLoad(”text/curro.txt”);
The requests generated in the List box would need to be changed too, but that’s just a Client change for requests.
Thanks for that great example of extending a design pattern!
Kindest regards,
Bill
I was wondering about the TextLoader and its responsibility. To me it seems that the TextLoader should be just just for loading text, and should not have a reference to a TextField and also shouldn’t instantiate it.
I really like the elegance of the examples and definatly use them myself, but context.doLoad(”swf/p0.swf”); tells very little that is also renders the swf when loaded.
I am probably being very picky here….:)
Hi Jiri,
Good points all and I don’t think you’re being picky. One of the problems that will probably have to be addressed in a separate post is the whole issue of dealing with placing objects on the stage. Where to introduce the TextArea is a real issue, and Curro chose to place it with the class used for loading. It worked well, but I imagine that you’re wondering about the principle that classes should do just one thing. Well, I guess you could say that Curro’s class did one thing–took care of loading external text and placing it on the stage. However, like I said, that’s an issue needing more discussion.
As for context.doLoad(”swf/p0.swf”)…well that doesn’t have to tell you much. In this case, it simply loads the first file in the constructer function. With Curro’s added class, we can use that same operation to load text instead of just SWF/graphic files. The function doesn’t care because it addresses it through the Context class–the little beauty that will handle any encapsulated algorithm that you throw at it.
The important focal point is that you can add different classes that do different things (loading text in this case) without having to unravel and re-write the entire program.
Thanks as always for your intelligent comments.
Kindest regards,
Bill
I agree and I fully understand the focal point of the article.
Would you think the following solution would be usefull.
Have the Abstract class ILoadMaster implement a method like: getLoadContainer():DisplayObject
That way we can return either a TextArea, TextField, Sprite , etc. and do all sorts of stuff to it.
Jiri
Hi Jiri,
I like that idea. Why not re-write the interface and a concrete class to show how you’d implement it and then request it from the Client? I cannot tell you how many times I’ve wrestled with DisplayObject–often coming in second.
Thanks again,
Bill
NoteThis is a response to the last comment
Hi Jiri,
I do agree with you that instantiating the text area (or a text field) inside the TextLoader class is not very elegant but as the IMasterLoader interface stands there is no other way as far as I know.
The same happens with your version: the getContainer function returns a display object and you cannot turn a text file into a display object unless you put it inside one.
Unlike the Loader class, the URLLoader class is not a display object and you do need a URLLoader object to load a text file. If you try to load it with the Loader class you get a IOErrorEvent 2044.
It occurs to me right now that we could have getContainer return a “*” type and then have a concrete TextContext class to instantiate the textfields, textareas or whatever and deal with the incoming data. I don’t know how to do this myself but I think I will give the idea a try.
Well, I think this discussion is really interesting and instructive.
Thank you Jiri and Bill for your help.
Curro
BTW: how can you format the text in this blog?
Hi Curro,
You format text just like HTML. However for listings use:
<pre lang=”actionscript” >
–code here–
</pre>
Also I have to use UTF-8 character codes for things like < and >
Take care,
Bill
Hi Bill and Jiri,
I have re-written the interface and added a getContent():* function.
Here is the new ILoadMaster class:
I have also modified the Context class:
I had to add two new Context subclasses: PixContext and TextContext
PixContext is just a copy of the old Context class:
For TextContext I have found a not very elegant solution but it works:
Then of course I had to modify the TextLoader class:
PixLoader stays just the same. It doesn’t even need to use the getContent method:
Finally I changed the method seeNow in the Client class:
Of course, the first context var in the Client class has to be changed to :
private var context:Context=new PixContext(new PixLoader());
I am not sure all this is better than the old TextLoader class instantiating a text area. What do you think? For me it is, at least, more complicated.
Regards
Curro
Hi Bill,
sorry about the formatting do I have to use the utf-8 codes for the pre tags? are they < and > ?
Thank you
Curro
Hi Curro,
In your code just type in the symbols as you always do. Your code was fine. I just added the <pre> tags to format it–never use the UTF-8 code in your programs.
A lot of developers (myself included) have used multiple Context classes–an abstract base class and multiple concrete implementations. However, I’ve been going the other way–towards a single concrete Context class.
I suppose either way works. Anyway, the question to ask with design patterns is, what will happen if I make changes? As long as you can keep the relations loose and functional, you will find many variations that you can work with.
Thanks for all your interest and very nice work.
Kindest regards,
Bill
@Curro You are right with the wildcard as a return type. I was thinking about it myself, but was thinking you would always have to case the return type.
Thinking about the question “what will happen if I make changes” I would go for the solution of Curro, becuase it is the most flexible one.
It would be nice to encapuslate the creation of the Context to and get rid of the switch/case, but I guess that would become a over designed thing :)
Jiri
Bill, one more question. I think it would be a very interesting topic to write about object pooling. There are allready some nice classes out there. I recently developed in interest in it, because using them can mean a huge speed performance.
Hi Jiri,
Wow! You sure can pick the topics! Object pooling in design patterns is fairly controversial, but I agree it would be a good topic–just to see what the pros and cons are.
In some respects, we all want more speed, but with the speed of current memory and CPUs, it’s not the issue it once was with the old 8-bit processors and severely limited memory. Instead, the issue of speed has shifted to design and re-design. However, I’m a sucker for squeezing more speed from a program (as the Flyweight patterns does) and it is something that I think is worth a post. However, here’s a list of what I have to cover first:
Deal with my client’s project
Finish re-writing a video player
Posts on the following topics:
Open/Closed Principle
Dependency Inversion Principle
Least Knowledge Principle
Hollywood Principle
One reason to change principle
Part II of Builder Pattern
Possibly Chandima might be interested and we could have something sooner, but until I get these other projects off my desk, I can’t put anything new there. However, it is a perfect topic for this blog. (Maybe you’d like to write a post on it?)
Thanks for the great idea,
Bill
Would it be appropriate to write a context interface, so that clients could also utilize polymorphism instead of typing to the concrete implementation of that context?
For example in the client…
protected var _context:IContext;
protected function init():void{
_context = new ConcreteContext(”someUrl.swf”);
}
Hi Tyler,
Polymorphism can be found in the Strategy classes themselves—they are written so that depending on the context of their use, they will have different meanings. I believe that we did type to the interface and not the implementation.
Kindest regards,
Bill