ActionScript 3.0 Prototype Design Pattern: A Minimalist Example
The Recursive Clone
In describing the Prototype design pattern, the Gang of Four indicate that in the collaborations, the client asks a prototype to clone itself. (Go clone yourself!) As innocuous as that sounds, it turns out to be more than a little work, and the pattern, as GoF indicates, is tricky and easy to get wrong. With ActionScript 3.0, my response is, “…you have no idea!”
In a couple of earlier articles relating to the Prototype design pattern in this blog (ActionScript 3.0 Clone and ActionScript 3.0 Recursive Excursion) we looked at some of the issues relating to key elements of the Prototype design pattern, and if you’re thinking of using the Prototype pattern, you might want to take a look at them and some of the comments that readers have made. I’d prefer not to re-hash them here so that we can focus on the design pattern and not its components or underlying processes that we’ve already discussed. So to get started, let’s take a look at the Prototype class diagram in Figure 1:
Figure 1: Prototype Design Pattern
Because the pattern includes a Client class, you can see right away where the client connects to the other participants in the pattern and something about the nature of the relationship. The key here is that the client holds an object reference to the Prototype class. So the client is going to have some kind of Prototype reference.
The second key element is the recursive nature of the cloning process. Each concrete class clones itself with a method inherited from the Prototype class. The problem, of course, is where are we going to get a cloning method and how can it be implemented recursively? One solution is simply to build an abstract class that includes a cloning process and then make the Prototype class a subclass to pass on the clone method. That’s what I did, but by keeping the CloneMachine class abstract, no instance of the CloneMachine class could be instantiated in the Prototype class. Nevertheless, I now had access to a cloning method. In some respects that sounds like strong-arming a solution, but I don’t think so. The Java solutions implemented Clonable in the Prototype class and C# solutions used MemberwiseClone and [Serializable] in their Prototype class (among other solutions). The result is that the clone method doClone(obj) from the inherited class is available for creating a clone method in the Prototype class. In the end, I came up with the design shown in Figure 2:
Figure 2: ActionScript Prototype Pattern
I cannot claim originality in subclassing one abstract class with another. GoF have a few examples, such as an application on page 224 where a Widget class is a subclass of a HelpHandler class—both are abstract classes.
The CloneMachine and Prototype
The first step is to build the class containing the clone method. As described in the previous article on cloning, this methods uses the ByteArray.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* Do not implement: Treat as Abstract Class */ /* Utility class : Cloning method*/ package { import flash.utils.ByteArray; public class CloneMachine { private var cloneWork:ByteArray; public function doClone(source:Object):* { cloneWork = new ByteArray(); cloneWork.writeObject(source); cloneWork.position = 0; return (cloneWork.readObject()); } } } |
Now that the clone method is available, it will be used to generate the abstract clone method in the Prototype. This makes it a little easier to use the try..catch..finally statement to check for errors and neatly return the cloned object.
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 | /* Prototype class */ /* Do not implement: Treat as Abstract Class */ package { import flash.errors.IllegalOperationError; public class Prototype extends CloneMachine { public var breed:String; public var description:String; public var unique:String; public function clone(obj:Object):Object { var clone:Object = null; try { clone = super.doClone(obj); } catch (e:ArgumentError) { trace(e); } finally { return clone; } } public function getDescription():String { return description; } public function getBreed():String { return breed; } public function getUnique():String { return unique; } public function setDescription(string:String):void { description = string; } public function setBreed(string:String):void { breed = string; } public function setUnique(string:String):void { unique = string; } } } |
The clone method is set up by a simple reference to the parent method (clone = super.doClone(obj);). Placed in a try..catch..finally statement, it catches any errors in cloning the object. Otherwise, it returns a clone. Several different get/set functions provide a set of properties for the prototype. The last property, unique is overridden in the two concrete Prototype classes for the purpose of example.
Concrete Prototypes
Keeping everything at a minimal level only two concrete prototypes are introduced, Dog and Cat as shown in the following two classes.
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 | // ActionScript file //Concrete Prototype: Dog package { public class Dog extends Prototype { public var doggyTreat:String; override public function getUnique():String { return doggyTreat; } override public function setUnique(yum:String):void { doggyTreat=yum; } } } / ActionScript file //Concrete Prototype: Cat package { public class Cat extends Prototype { public var kittyToy:String; override public function getUnique():String { return kittyToy; } override public function setUnique(playful:String):void { kittyToy=playful; } } } |
As you can see, the two concrete classes do nothing more than provide a single setter and getter pair to illustrate that they are different and yet part of the Prototype.
The Client Makes a Clone
The final step in this minimalist Prototype pattern is to build the Client. The client holds a reference to the Prototype class by creating an instance of the Dog and Cat classes, typing both as a Prototype. Then, using a recursive clone, each instance creates a clone of itself.
Lastly, the clone objects are then traced to view the property values of the cloned objects. This last step is to be sure that the cloned objects actually have the properties and property values of the originals.
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 | package { //Client import flash.display.Sprite; public class Client extends Sprite { private var tDog:Prototype; private var cDog:Object; private var tCat:Prototype; private var cCat:Object; public function Client() { tDog = new Dog(); tDog.setDescription("Big compulsive brown, black and tan"); tDog.setUnique("Bacon"); tDog.setBreed("Greater Swiss Mountain Dog"); cDog = tDog.clone(tDog); trace(cDog.breed); trace(cDog.description); trace("Treat: "+cDog.doggyTreat +"\n"); tCat = new Cat ; tCat.setDescription("Sleek, independent, black and tan"); tCat.setUnique("catnip"); tCat.setBreed("Siamese"); cCat = tCat.clone(tCat); trace(cCat.breed); trace(cCat.description); trace("Favorite toy: "+ cCat.kittyToy); } } } |
You will see the following output when you test it:
Greater Swiss Mountain Dog
Big compulsive brown, black and tan
Treat: Bacon
Siamese
Sleek, independent, black and tan
Favorite toy: catnip
Before looking at the uses of the Prototype, you should be aware that the cloned objects do not have the methods of the original. For example, the tDog instance can use all of the methods of both the Prototype and Dog classes. However, the cloned instance, cDog cannot use any of them. We had to have a public property declared in the Prototype and concrete Prototype classes to bring out the properties and their values in the clones. That is, rather than being able to use the getter methods, we had to refer directly to the properties. For example, we had to use
cCat.kittyToy;
instead of,
cCat. getUnique();
That’s a little mystery I’d like to solve.
Uses of the Prototype
As is often the case in looking at design patterns, the best use case I found was in Head First Design Patterns. The Freemans suggest a monster maker where prototypes of monsters would be used to generate clones in a game where monsters were routinely dispatched and re-generated. Cloning would be simpler and less expensive than recreating new monsters in a rapidly changing environment. The idea is to make a prototypical instance and then clone it whenever the system requires a new one. This is especially useful when the classes to instantiate are done so at run-time. In a an environment where any combination of creations are required at unknown points, the Prototype is one pattern to consider.
Related posts:



Bill Sanders
Why not just use ObjectUtil.copy()? You’re doing the exact same thing with your base class as is executed there.
There is also a problem with serializing data wherein you have to use registerClassAlias in all your subclasses to make cloning work…
Hi Michael,
That sounds like a good idea. Would you mind providing a Prototype class example using ObjectUtil.copy() to illustrate exactly what you mean? (Just the Prototype class–not the whole pattern.)
Also, since serialization is a key issue, could you elaborate a bit on what you mean by registerClassAlias required in all subclasses?
While the example I made is very simple, I had to jump through several hoops to get it working right and the way GoF intended as far as I understood it. I’m hoping to add something a little more substantive using the Prototype design pattern, and I’d really like to see an alternative to the ByteArray clone.
Thanks for the idea,
Bill
Maybe this is an interesting article on how to copy the object and preserve the methods.
http://blog.comtaste.com/2007/10/improving_object_copy.html
If you want your cloned object to inherit the methods of your initial object, you might wanna try either
1 ) registerClassAlias(“Cat”,Cat);
2 ) putting the metadata tag [RemoteClass(alias="Cat")] on top of your cat class.
Jiri,
Thank you for the link. That is an interesting article on cloning in ActionScript 3.0. I believe that readers of this list will find it very instructive.
Kindest regards,
Bill
Simon,
I will definitely try that. Maybe you could provide a little more information to illustrate exactly how you’d recommend doing that.
Thank you very much,
Bill
Hello Daniel,
Вы для картины конструкции прототипа
I tested your program, and it works perfectly. Is there anything you’d like to say about it?
Сердечные приветы,
Bill
When I was searching for solution to the problem of cloning a week ago, I found your blog. It realy helps me!
I started experimenting and make this example.
Many people come to this site to find a solution to this problem, I believe that my decision should help them.
From Russia with respect,
Данила
Hi Daniel,
Thank you for the feedback, and Chandima and I are very glad we could be of some help. I know that our readers will appreciate your code.
Kindest regards,
Bill
There is one quite major problem with the above approaches. Unfortunately you can’t deep-copy complex objects that expect parameters to be passed to their constructor using ByteArray (except if all constructor parameters have a default value). However you can copy the complex properties of the object you are copying (this can be done by implementing IExternalizable in your concrete Prototype and writing / reading its complex properties manually ).
A workaround would of course be not to use the ByteArray deep-copy approach, but instead define explicit clone():* {} methods in the subclasses that create an instance of the class, populate and return it.
Hi Barna,
Thanks for pointing that out. Since this article was posted almost 4 years ago, we’ve been doing a lot with Bitmap and BitmapData objects. They’ve become very important for moving bitmap data through slower processing environments, particularly mobile devices. In fact, your suggestion using clone() [BitmapData.clone()] is what we used with a 2012 post. We want to do more with using ByteArray and have not yet tried working with ByteArray.clone(), but that is something that is definitely on the radar.
Kindest regards,
Bill
Hi Bill, yep I saw that the post is quite old. I just wanted to point that little thing out because ActionScript 3.0 didn’t change significantly in the past 4 years and the issue remains.
BitmapData is a tiny bit more special since it has a native clone(); method whereas custom objects have to define their own clone(); methods ( again, I only wanted to point out that the ByteArray deep-copy approach you have used in the post doesn’t really work when trying to copy complex objects that expect some mandatory parameters in their constructor ). Cheers!
Hi Barna,
Okay, I see your point. If you have any ideas about speeding up bitmap data for mobile devices, send it along.
Cheers,
Bill
Well, although it is not about speeding up bitmapData, I suggest looking into Stage3D ( how to create GPU accelerated grapgics ) and maybe the Starling Framework that is built on top of it. I think Stage3D is not yet fully suported on mobile though, but in theort it will eventually ( “soon” ) be.
Hi Barna,
Actually, the experiments with bitmap data classes and methods has been about speeding up operations. The primary idea is to create->clone to remove a ‘new’ step, but that may not work either. Yes, Stage3D and Starling are speed-up elements as well. I am trying to work with them with Flash Pro, but I’m finding that I’ll probably have to use Flash Builder.
Hey! What happened to your Swiss icon?
Kindest regards,
Bill
I have no idea what happened to it!
Maybe I accidentally mistyped my E-Mail address ( posted the reply from the phone ) and since Gravatar is linked to it, that might be why it got messed up ( unfortunately there is no Edit option for replies ).
Unfortunately I do not know for sure how the bitmapData.clone() works internally, but chances are that it’s just also creating a new BitmapData instance populated with the current information ( which indeed doesn’t lead to any performance gain ).
ActionScript 3.0 is quite tricky with Prototypes… Everything eventually comes down to instantiating “new” objects and initializing them with current data ( even in the case of ByteArray once you call readObject() – if I am not mistaking, the internal mechanism called just also creates “new” instances when recreating the object ).
As for the Stage3D Flash Pro thingie… I haven’t used Flash Pro for at least 5 years now ( been only using Eclipse / Flash Builder since ). In Flash Builder you surely can configure the project correctly to use Stage3D (I tried it myself 1-2 weeks ago) and as for Flash Pro, maybe give the following a shot: http://stackoverflow.com/questions/8249203/getting-started-with-stage3d-in-flash-cs5-and-which-framework-to-choose
Hi Barna,
Thanks for the link. I’ll follow it up. Somehow I have FB 4.6 on my portable and FB 4.5 on my main computer, and I believe that Stage3D works best with FB 4.6. I’ve used FB before, but I still like Flash Pro’s ability to ease the drawing process, and I need that in game development.
I’ve been thinking of running some Stage3D posts as well as some other things related to speed that are in the works. It seems that Flash is heading to three areas:
1. Mobile development
2. Game development
3. Video
Of course I am hoping for concurrent development as well.
I see you got your “Swiss” back on!
Kindest regards,
Bill
Hehe, my “Swiss” is indeed back on (didn’t mess up the E-Mail address this time ). As for game development: although I don’t do game development on a daily basis, I am planning on getting my hands wet with it sometime in the near future. Flash Pro I’d use exclusively for creating animations and nothing more. For development, Flash Builder is light-years ahead of Flash Pro and will most likely always be ahead (it has proper code hinting, proper debugger, profiler, code templates, refactoring options, ability to install “proper” plug-ins like Subclibse for version control, etc. ).
I can not imagine myself going back to Flash Pro for development, I’d rather switch technology all together or start writing code in Notepad++ (I am not saying that Flash Builder is perfect, it’s far from perfect but it’s a more mature IDE for “proper programming” than Flash Pro will ever be).
Just my 2 cents.
PS: Flash is definitely heading towards Game Development. In my opinion the only chance the technology has to grow in the Mobile scene is if the people at Adobe stop writing sloppy code (don’t even dare looking into Flex sources) and get Stage3D right (if they can get at least the GPU acceleration right for the moment, it will already be a huge improvement and it will surely open up new doors for Air when it comes to Mobile / Tablets).