06.12.2011 21:57
Singletons in Flash [basic]
In today's post I will write a little about singletons, which are objects that exist in only one instance - what are they, how to make them in Flash and what are they useful for.
Singleton is a design pattern and like many of those it might appear to overcomplicate things that can be done it much simpler way, however the truth is in return we get much cleaner and more specialized code which is especially useful when working in bigger group or when we often go back to older projects that we have already forgotten, although even smaller, single handily crafted applications will benefit from this solution.
When creating a singleton class we want to have only one object for it in the whole system, in such way that we will always access the same properties independently of the calling location. In most well-known programming languages it can be done by simply writing:
Singleton is a design pattern and like many of those it might appear to overcomplicate things that can be done it much simpler way, however the truth is in return we get much cleaner and more specialized code which is especially useful when working in bigger group or when we often go back to older projects that we have already forgotten, although even smaller, single handily crafted applications will benefit from this solution.
When creating a singleton class we want to have only one object for it in the whole system, in such way that we will always access the same properties independently of the calling location. In most well-known programming languages it can be done by simply writing:
private class Single { private static const instance:Single = new Single(); private function Single():void { } public static function getInstance():Single { return instance; } }Unfortunately it won't be the case for Flash, since it doesn't support constructors in private space, which is why we have to work around this problem usually by introducing a parameter that third party won't be able to supply correctly:
public class Singleton { private static const instance:Singleton = new Singleton(getInstance); public var myVar:Number; public function Singleton(f:Function = null) { if(f != getInstance) throw new Error("You cannot instance Singleton! Use getInstance() instead."); myVar = 5; } public static function getInstance():Singleton { return instance; } }Well, that is pretty much it, however it is hard to point out any particular advantage for Singletons in this example, that is why we will for something a bit more complex, i.e. application's sound controlling class. Usually in case like this we want to hold all sounds in once place to easily read, play and pause them at the same time, which is a perfect reason to use the singleton pattern like this one (in very simplified form):
public class SoundControl { private static var instance:SoundControl; private var bIsLoading:Boolean; private var aQueue:Array; private var aSounds:Array; public function SoundControl(f:Function = null) { if(f != getInstance) throw new Error("You cannot instance SoundControl! Use getInstance() instead."); aSounds = new Array(); aQueue = new Array(); } public function play(name:String):void { if(bIsLoading) { aQueue.push(name); } else { aSounds.push( new Sound(name) ); /* play sound */ } } public function stopAll():void { for each(var snd:Sound in aSounds) { snd.stop(); } aQueue = new Array(); } private function loadAll():void { bIsLoading = true; /* load all sounds and call onLoaded when done */ } private function onLoaded():void { bIsLoading = false; /* play all sounds stored in aQueue */ } public static function getInstance():Singleton { if(instance == null) { instance = new SoundControl(getInstance); instance.loadAll(); } return instance; } }SoundControl seems to do a lot, but an "outside" person will only see three functions: getInstance(), play() and stopAll(), which is enough to properly control all the sounds in the application, while leaving all the dirty work (volume control, channel assigning, resources managing etc.) to us, the class creators. Additionally we will always be certain that no one will create their own private SoundControl to play sounds that no one else would be able to access because they belong to a different SoundControl object than the one we all agreed to use...