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.

The ActionScript 3.0 Prototype Design Pattern: A Minimalist Example 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
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