The ActionScript 3.0 Flyweight Saga: Part I
I ran across the Flyweight design pattern when looking for a pattern that could be used to speed up placing objects on the stage in a Flash application using ActionScript 3.0. The Flyweight name implies a somewhat insignificant design pattern, but after working with it for a few months I found it to be both powerful and informative. It is powerful in that it is one pattern that actually speeds up operations, and it’s informative in that key OOP concepts are used and illuminated in it. It’s also one that has taken a while to really put together right—a process I’m still working on. Because this is a work in progress, I’d like to invite any and all developers with an interest in ActionScript 3.0 and design patterns to comment.
The Flyweight Basics
Imagine a situation where you want lots of buttons on the stage as a UI for information access. This is a pretty common situation and so a worthwhile effort if it works as it’s supposed to. You can use a component button from the Button class by importing it from fl.controls or build one using the SimpleButton class. The intrinsic features of a button are pretty similar—the way it works, looks and listens for events. However, the extrinsic features of buttons depend on their context. The position of a button on the stage, what it does with events, and what actions it calls forth are context dependent features. In a nutshell, the Flyweight separates the intrinsic from the extrinsic. The intrinsic state of an object is stored in the Flyweight. This information is context free and can be shared with all buttons. In fact, the Flyweight is a shared object. So instead of having several objects, you have one objects shared by many.
The example used by the Gang of Four is an application that uses the Flyweight is a word processor. Each character (glyph) is an object, and a word document contains a lot of character objects that are constantly reused. The intrinsic state of a character, like the letter “e”, is pretty standard. However, the extrinsic state changes with its position on the page (context). By reusing a single intrinsic state for each object, you can save a lot of time over creating a new one each time it’s needed on a page. So, the Flyweight stores the intrinsic state and then just changes the Flyweight’s extrinsic state to the desired position on the page. In the application planned for this article, instead of glyphs, we’ve got buttons, and just like the glyphs, all we need to do is the position them on an x/y grid.
Flyweight Overview
To get started, take a look at the Flyweight class diagram :

Flyweight Class Diagram
Like all of these diagrams, it takes some study to see what’s going on. (It took me a lot.) You’ll find some interesting relationships among the classes in the Flyweight pattern. First of all, the relationship between the FlyweightFactory and the Flyweight is one of aggregation. The factory class is the aggregator and the flyweight interface is the aggregate. You can think of the factory class owning the interface in the context of aggregation.
Second, the design pattern specifically includes the Client as a class. This means that the client has a responsibility in the pattern and references Participant classes. About half the patterns in the GoF book include a Client class. Chandima’s article on the Composite pattern also includes a Client class in the pattern. (If you see a gray Client class in a diagram that means that the Client is not part of the pattern, but is a handy tool to show which Participants interact with the Client class.)
Third, the pseudocode annotation associated with the FlyweightFactory class helps to give you a better idea of what is going on in the class. These annotations are extremely helpful in understanding exactly how the operations are implemented. However, as you have no doubt learned, when you implement in ActionScript 3.0 you need to design for ActionScript 3.0, which can be significantly different from say Java or C# where you will find most examples.
An Abstract Flyweight in ActionScript 3.0
One of the problems in creating any of the patterns described by GoF or in the Freemans’ wonderful book, HeadFirst Design Patterns, is that they’re written in SmallTalk or Java. What’s more, they use some of the really cool built-in features of those languages that are not available in ActionScript 3.0. The Flyweight is no exception, plus the fact that it’s not expanded in HeadFirst Design Patterns. So getting started has meant finding out how to work out a sensible alternative to hash tables (associative arrays) and decide whether to use an abstract class (which is not available in ECMAScript 4) or an interface, that is.
Fortunately for me, Jim Kremens, a top notch NYC Flex 2 developer, had an example of the Flyweight design pattern he shared with me. I made a few changes to suit my tastes, but it is basically Jim’s design. I swapped an interface with the “abstract class” (see Chandima’s article, Runtime Checks for Abstract Classes and Methods in ActionScript 3.0 on this blog.) Also, Jim used the Array class for creating an associative array, which works fine. However, the ActionScript 3.0 docs suggests using the Object class for associative arrays, and so I changed the Array class to an Object class. That’s not a lot of changes, and Jim’s design is strong enough to incorporate the changes with very little alternations to the code. Finally, I made the miniscule changes reflecting the switch from Flex 2 to Flash CS3 API.
ActionScript Abstract Flyweight Example
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 72 73 74 75 76 77 78 79 80 81 82 | package { //Flyweight interface public interface IFlyweight { function build ():void; } } package { //Flyweight Factory public class Factory { protected var objects:Object = {}; public function Factory () { objects["X"] = new FillObject(); } public function Retrieve (key:String, ...rest):IFlyweight { switch (objects[key] != undefined) { case (true) : break; case (false) : objects[key] = rest[0]; break; } return objects[key]; } } } package { //Concrete Flyweight: Fill public class FillObject implements IFlyweight { public function FillObject () {} public function build ():void { trace ("Build FillObject"); } } } package { //Concrete Flyweight: Stroke public class StrokeObject implements IFlyweight { public function StrokeObject () {} public function build ():void { trace ("Build StrokeObject"); } } } package { //Client class import flash.display.Sprite; public class FlyweightTest extends Sprite { public function FlyweightTest () { var factory:Factory=new Factory ; var x:IFlyweight=factory.Retrieve("X");//"X" already exists x.build (); var y:IFlyweight=factory.Retrieve("Y",new StrokeObject ); y.build (); var z:IFlyweight=factory.Retrieve("Z",new FillObject ); z.build (); } } } |
As you can see from both the code and the class diagram, the Client class (FlyweightTest) does not get stroke and fill objects directly from the concrete flyweights (stroke and fill) nor the IFlyweight interface. Instead it relies on the Factory class. To make this whole thing fly (no pun intended), Jim used the keyword, …rest. By placing the …rest keyword in a function’s parameter (called a rest parameter), the function will accept any number of comma-delimited arguments. In the Retrieve method in the Factory class, the rest parameter can be used to identify the specified concrete flyweight identified by the associative array’s key word. If the key is recognized as existing already in the case statement, the existing instance is returned. Otherwise the Factory cooks up a new instance. We can see this in the output:
Build FillObject
Build StrokeObject
Build FillObject
The first FillObject with the X key was already built in the Factory ; thus, it was not undefined. So, it just jumped out of the switch structure and returned the X object, which was a FillObject. The second key, Y, was a StrokeObject that had not been defined, and so the factory built one. Likewise, with the Z key, no key named Z had been defined; so it created one, which happened to be another FillObject.
The concrete flyweights, both of which have implemented the IFlyweight interface, hold an intrinsic state. However, because we have no extrinsic state as a parameter, we may have a shared object, but we have no information for the extrinsic state. Further, do we really have a shared object? Remember that the concrete Flyweight can be a shared object. So to test the example code for shared objects, we need to change the client (FlyweightTest) so that multiples of the shared object can be seen. To do this, I created a new concrete flyweight, FlyButton, representing the object that I eventually want to be used as a shared object. Likewise, I created a new client class to test the whole thing (FlyweightShared). The following two classes can be placed with the other participants and then tested in either Flash CS3 or Flex 2:
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 | package { public class FlyButton implements IFlyweight { public function FlyButton () {} public function build ():void { trace("I'm a shared button. I think..."); } } } package { package { //Client class import flash.display.Sprite; public class FlyweightShared extends Sprite { public function FlyweightShared () { var factory:Factory=new Factory; var firstOne:IFlyweight=factory.Retrieve("ButtonFly"); firstOne.build (); var secondOne:IFlyweight=factory.Retrieve("ButtonFly"); secondOne.build (); var thirdOne:IFlyweight=factory.Retrieve("ButtonFly"); thirdOne.build (); } } } |
In addition, we’ll need to make a slight change to the Factory class. Now it reads:
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 | package { //Flyweight Factory public class Factory { protected var objects:Object = {}; public function Factory () { objects["ButtonFly"] = new FlyButton(); } public function Retrieve (key:String, ...rest):IFlyweight { switch (objects[key] != undefined) { case (true) : break; case (false) : objects[key] = rest[0]; break; } return objects[key]; } } } |
This time, I got the same output for all of the three variables in the output window:
I'm a shared button. I think...
I'm a shared button. I think...
I'm a shared button. I think...
You may be wondering the same thing I am: “Is this really a shared object, or does it just instantiate three instances like you could do using var button:Button = new Button()?” If it’s a shared object, then we ought to have a much speedier and less processor-intensive structure. Otherwise, we’ve just succeeded in a convoluted way of creating a button. Tune in next time to see what’s up or leave a comment to straighten me out on this. In addition, we need to so something about that pesky extrinsic state, not to mention using a real button and not just a trace statement.
Related posts:

Bill Sanders
Hi Bill,
Interesting article, but why would i benifit from using a flyweight pattern over a factory pattern, they seem to do very similar things.?
darren
You say, “By reusing a single intrinsic state for each object, you can save a lot of time over creating a new one each time it’s needed on a page.”
But you are doing this:
var y:IFlyweight=factory.Retrieve(“Y”,new StrokeObject );
and then in Retrieve(), if the key exists, you are just throwing away that newly created StrokeObject.
Why not move the new statement inside the factory so it only gets created when needed. As is, the factory doesn’t create anything. That would require some logic within the factory to know what kind of objects it can create, but that could be abstracted as well.
The way it is now, the client has to somehow keep track of the key/values in the hash map of the factory. What if I say:
var y:IFlyweight=factory.Retrieve(“Y”,new FillObject );
I think I’m creating a FillObject (actually I am, and it’s getting thrown away) but I’m getting back a StrokeObject.
Darren, I would say that the difference between the flyweight and a factory, is that in a factory, you will probably get a NEW instance of the type of object you request each time. In the flyweight, you would just get the same instance every time you asked for that type. You could *almost* think of it like a singleton factory.
Keith, I see your point, I am still having a little trouble thinking of what I would use a ‘singleton Factory’ apart from data movement, but then I could just use a singleton…
*rubs head.
*gets out head first into Design patterns book.
Keith,
Thanks for your comments. Keith, you’re absolutely right, the Factory does need a new constructor. As you saw, Jim’s original script had one, and I started getting tunnel vision on creating multiple uses of the same object–shared object. Sooooo, I changed the code so that it now has the object created in the Factory.
What I really need to do is to get something like this going in the Factory:
The array will have all the info and each Button will be state-free but be positioned.
That was not too clear, but it’s the general direction I’m heading.
Hi Darren,
I’m going to talk to Chandima about the Factory Method and the difference between it and the Flyweight. I think I know what Keith meant in reference to a ‘Singleton Factory,’ but let me see if I can find another way of putting it.
Bill
Hi again Darren,
I think I have the answer to your question and to a lot to my own. The Factory Method pattern does not inlcude the Client as a participant in its structure. I’ve been (incorrectly) assuming that the Factory participant in the Flyweight pattern holds the state for all (that’s ALL!)of objects (buttons in this case). However, it’s the Client that does. So I’m going to have to wrap my head around the Client to figure out how it holds all of the states, while the buttons will be state-free objects…my brain just left on vacation for Acapuco…
Stay tuned,
Bill
Not a pattern I’ve ever used so my knowledge is simply from academic curiosity. It seems, (from my understanding of FlyWeight) that the FlyWeight-Factory is intrinsic to its actual deployment. Every version of Flyweight I’ve seen seems to deploy it in some form or other. I definitely find the theory interesting – Apparently in a situation where multiple instances of a class are needed you create an object based on intrinsic rather than extrinsic values thus reducing the number of created instances. The extrinsic value are passed as an class instance property rather than be created as a unique class
An example would be a school with a population of 5000, 3000 chicks and 2000 dudes. Thus we have 2 class, Dudes and Chicks each possessing the property “population” to which the value can be passed. I’ll post my test class/package when I’m done with my muckabouts
aYo,
Thanks for that. I’d really like to see what you develop. My next step is going to be to see how to set up the client to maintain all of the state for all of the virtual button objects. (Actually, I’ll have to use “trace” buttons” until I get the structure right.) I’ll probably stick with Jim’s original Factory structure with the exception that the associative array will be based on an Object class rather than an Array class, and I suspect that the original Client class the Jim made has some important pointers as well.
BTW, I like the ratio of 5:3 in your example. ;O
Bill
Hi Bill,
I wrote this Flyweight example a few years ago (in AS2, of course) when I ported eight design patterns to AS in order to learn how they worked. After I got it working, I didn’t think about it too much… Over time, I ended up using lots of the other examples, but never the flyweight. Now I see why…
If you need to create a bunch of buttons on the stage, all of them need to be unique instances. You can’t put 3 copies of the same button on the stage and then set 3 different x and y values for that button. Each time you set the x and y values, as you are dealing with only one actual instance, you’ll overwrite the last value you set. They must be discreet instances to have unique property values.
One application I can see of the flyweight is the following: you could use it to configure your button instances. In other words, you might create one ButtonConfigure object that contains values that you know will remain constant for all of your buttons. Then, although you still have to create unique button instances, you can use the same configure object to set properties common to all of them. Properties that need to be unique would be set separately. This is sort of how stylesheets work…
That might be pretty cool… You could configure your button class to accept different ButtonConfigure objects. That would give you a lot of flexibility – the Button class itself could remain really generic – different configure objects would produce very different buttons.
That problem has been solved before, and in most cases without the flyweight. But if you’re looking for an application of this pattern in AS, I think that might be a good one…
I’m not clear on why this pattern might be more valuable in, say, SmallTalk. I’d be interested to learn about that…
Jim Kremens
Hi Jim,
I believe you’re right. I had chatted with aYo some about it, and he too reached the same conclusion. Also, I arrived at the same conclusion you did. First, I think I’m going to try and tackle the extrinsic state as a parameter in an operation. This will also be abstract, but I’m trying to clarify (for myself as much as for anyone else) the role and use of instrinsic and extrinsic states.
I’ve spent so much time with the State design pattern that when I think of states, I too often think of it in that context. What I need to do is to get better clarity on how to work with those states as intrinsic and extrinsic and the whole concept of a stateless object.
You mention that you’re not clear on why the pattern would be more valuable in some other language. I don’t know if it would be. All I know is that it’s been difficult to study examples from SmallTalk and Java because often they use examples that include built-in features in those languages that are not in AS 3.0. However, if I said that they were more valuable in SmallTalk, I certainly didn’t mean it!
Thanks (yet again!),
Bill
“However, if I said that they were more valuable in SmallTalk, I certainly didn’t mean it!”
No, I just know that a lot of the Gang Of Four patterns are presented in SmallTalk, so I’d be curious to know why (or if) this sort of concept is more viable there.
Hi Jim,
I see now. My hunch is that GoF was working with SmallTalk just like we’re working with AS 3.0 and so they used it. Likewise, the Freemans (Head First DP authors) were working with Java and decided (correctly it would seem) that a lot of Java programmers would really like a good clear introduction to DPs.
As far as I’m concerned, I think that AS 3.0, even without gems like abstract and private classes, is as good a candidate for DPs as any language. Right now, most of the examples I’ve found have been written in Java and C#. My hope is that our discussion will bring in more ActionScript programmers and we can all learn from one another like we’re trying to do here.
I could do this night and day….and I’ll try and get Part 2 (of an unknown number of Parts) done soon.
Thank you mucho,
Bill
You know Bill, one possibility to explore that might work with Flyweight is drawing API skins. The Flyweight Factory would give back a skin object that would take in color or corner roundness as extrinsic properties in a draw method. Then general properties such as how that skin looked would remain consistent but a few variations would be available depending on the button.
Another note is about using …rest. You should never use …rest if you are only accepting a single parameter. In the example you only ever look at rest[0]. I realize it is just that, an example, but proper use and simpler use would have been to give it a default value of null, or rather in this case to leave it out altogether.
Now I need to read through your part 2 and 3! Great blog by the way.
Hi Jacob,
Thanks for your comments. I was able to get this DP off the ground thanks to Jim Kremens initial rendering, and that’s where I first noticed the ..rest parameter. Also, I think that an array was used and I changed it to an associative array (Object) and hung on to the …rest parameter. Others have mentioned the same thing you did about the use of …rest. It’s not so much that it works; it’s that I’m not sure why it lacks that would make it a poor choice. As I keep pounding beyond the FlyWeight, I keep coming back to this same issue, and it is quite helpful to get comments like yours. My problem is that I like going through the agony working to figure out a new DP and since the Mediator is next in line, the little time I have, I spend on getting some ideas for the Mediator. However, after your comments, I’ll revisit the FlyWeight again to see about making improvements.
Take care,
Bill
Quote:
“[The flyweight design pattern] is extremely useful when we need to have large collections of objects that are fundamentally the same except for a few parameters. In this case, we do not want to overpopulate our memory with lots of objects that are mostly identical, but instead we want to use system resources efficiently while keeping a uniform access interface.” (Daniel Sánchez-Crespo Dalmau, 2003)
If this is the aim for this design pattern, then the simplest and most effective implementation in Actionscript 3 would be as below, in my opinion.
Here’s my example using a Soldier in a game.
- The Soldier class itself has all instance-dependent information (e.g. current life) and all soldier functions (e.g. walk, fire).
- A full-static helper class contains all general variables (e.g. damage per shot) and all function implementations (e.g. walking behavior, firing behavior).
- The functions in the Soldier class simply call their flyweight counterparts and pass the current soldier instance, this.
Now, each soldier instance takes up minimal memory. The flyweight does the rest.
Am I deviating from the pattern? Is this approach more straightforward and efficient?
I am confused on what rest[0]; is ???
Hi Anthony,
The … (rest) parameter is one that I like to use when I have no idea what’s in an array or how long it is. In this case, I only wanted the first thing that popped up, and so I chose to grab whatever was the first element in the rest array. The method (from Part III of this series):
wants to check to see if there is an extant object, and if there is not, it builds one. You don’t have to use the word “rest” but its a handy one that is often used by developers, and so I just employed it. Here’s a little routine that shows different ways to employ the … rest parameter and that you can use different parameter names if you wish:
When you test it, you’ll see:
Larry,Mo,Curly,Shemp,4
Larry
Mo
Curly
Shemp
4
in the Output window.
It has its uses, and I think with the Flyweight it works well. By if there’s a better way, I’d be happy to implement it.
Kindest regards,
Bill
…rest is not required, just send it an object (string/etc)
public function FlyweightTest ()
{
var factory:Factory=new Factory ;
var x:IFlyweight=factory.Retrieve(“X”);//”X” already exists
x.build ();
var y:IFlyweight=factory.Retrieve(“Y”,new StrokeObject );
y.build ();
var z:IFlyweight=factory.Retrieve(“Z”,new FillObject );
z.build ();
}
this is a bad practice, avoid doing that.
Hi Ayu,
1. Why isn’t …rest required? What object should you use when you don’t know what’s coming?
2. What is a bad practice? Are you talking about using …rest or are you talking about what you set up as a factory?
Thanks for your comments, but please provide more information.
Kindest regards,
Bill
Hi Bill,
1. As every Actionscript 3.0 class extends Object, requiring an Object parameter effectively lets you expect one item of any type. You could also use the * type, like this:
private function doRest( parameter:* )
Best regards,
Timo
Timo!
It’s great to hear from you! How are things in Finland?
Okay, so you (and I think Ayu) are saying that instead of using …rest as a return argument, I should set up an object as a parameter.
Why? What advantages are there for using an object over …rest that will eventually end up in the same place–content in an object’s property?
Thanks for clarifying Ayu’s point, but what are the problems with …rest that are not a problem with an object data type?
Kindest regards,
Bill
Been a while!
Nice to see some activity here. I am from the Netherlands, though. ;D
You are right, technically the effect is exactly the same. However, …rest implicates that there should be some effect when passing multiple parameters – like filling an array with any number of initial items; the …rest makes sense.
Here, you expect one object of any type. Preferably, that should be clear from the function’s structure. Prevents human error and confusion!
I am wondering if you can pass ints, bools, uints, etc. where an Object is expected. If not, that’s where * comes in. Anyways, after working with C for a while, I’m not sure how Actionscript would handle this. Easy enough to try, though!
Cheers,
Timo
Hi Timo,
Sorry for getting the country wrong. The Netherlands…I spend one summer in Leiden at the Law School studying European crime and criminal justice. Fantastic justice system there. …I recall the Witch’s scale
Okay, I see your point and Ayu’s. Now, Ayu’s example makes perfect sense.
Thank you both for adding that.
Kindest regards,
Bill
(Off topic)
Hi Bill,
Not to worry
Sounds like you know more about Dutch law than I do. I am not familiar with the Witch’s scale!
As a matter of interest, have you checked out Haxe? (haxe.org)
It’s a multi-platform programming language that resembles AS3.0. Beautifully made. I have just started playing with it and I’m loving it.
For instance, you can make a Flash client and a PHP server both in haxe. You can serialize your objects to strings, pass them to the server (or client), unserialize them back to objects, and continue working with the very same objects. Entire data structures (such as arrays) can be serialized in a single line of code.
Absolutely magnificent!
Hi Timo,
Haxe sounds very interesting. I especially like the idea of working with both Flash and PHP together. I will definitely look at it.
The witch’s scale is in Nijmegen. I had no worries about being mistaken for a witch–they are light and airy so that they can fly. I easily tipped the scales! (I’m no flyweight.)
Cheers,
Bill
LOL!