Chain-able Decorators in AS3 With Proxy
[UPDATE: Some of the source files in this example won't be available. Please see the latest files in the guttershark repo, in gs.display.decorators]
I was briefly examining the decorator pattern in the “Advanced ActionScript 3 with Design Patterns,” which is great. But the mention of “chaining decorators” wasn’t fully brought to fruition.
I spent some time thinking about how exactly one would implement them with display objects. At first examination, the problem is that with a decorator, it needs to implement the same interface as the decorated object - which presents a problem. I don’t want to write the entire movie clip, or sprite methods. Bleh.
The solution is to create a decorator that extends proxy. If you call a method, or read a property on the decorator that’s unknown, forward the call to decorated object. Another key, is to make sure the decorator requires a dynamic object as the object to decorate.
Maybe that description was a little bit hard to understand. These examples should help explain:
First, make note of these two includes:
Then take a gander through these three decorators:
Optionally, with the “highlightable” sprite. It supports something called proxy through. Which is just a creative way for me to specify a different object to send unknown method calls or properties to. That’s what the second include is for.
The only awkward thing is that you can’t use these decorators with the display list. So you’d still have to add the base object to the display list, but then you can chain the decorators and use the outer-most decorator for methods/properties.
The examples zip file has updates for this new functionality.
Make note, that because the decorators use includes, you’ll need to make sure you’ve got the as and as_includes folder from the guttershark source. The reason the includes are outside of the classpath is because asdoc interprets the .as files as a class, which causes errors. And the reason for the includes in general is so I don’t have to repeat myself.
Enjoy.
4 Comments so far
Leave a reply
This is really interesting stuff — well done, and thanks for sharing!
Hi, this is great! I have been unhappy with the decorator pattern in AS for this very reason. However, how do I keep the type of the decorated object?
var o : MyObject = new MyObject();
o = new DecorateMyObject(o);
o.myOperation(); // myOperation() will be redirected correctly but the preceding line will not compile - o is not a MyObject anymore.
Hope this makes sense ;-)
@Martin, usually I do something like this:
var finalDecoratedObject:Decorator;
function MyObject()
{
var o:MyObject = new MyObject();
var d1:Decorator1 = new Decorator1(o);
finalDecoratedObject = new Decorator(d1);
}
The goal is to keep variable references around for the types of objects you need. In the above example, this would be if you only needed to reference the final decorated object. And I’m decorating “o” a couple times just for demonstration.
Thank you! I ended up creating a “Decoratable” superclass that all my classes (e.g. MyObject) inherit from. This superclass extends Proxy, like in your example. Then I can have a “Decorated” class that can decorate any instance of MyObject but is also of type MyObject. Thanks you your help.