In ActionScript 3, class constructors can only be set to public. Adobe has stated that this is because the ECMAScript specification is not yet complete, and they did not want to break forwards compatibility with the specification. This makes a lot of sense, but it leaves AS3 developers without a clear way to implement the Singleton design pattern. Luckily, there are a couple ways of faking Singleton functionality. Both solutions are kind of hack-ish, but they get the job done.
My first idea was to use errors to control instantiation:
// Singleton class: package { public class SingletonDemo { private static var instance:SingletonDemo; private static var allowInstantiation:Boolean; public static function getInstance():SingletonDemo { if (instance == null) { allowInstantiation = true; instance = new SingletonDemo(); allowInstantiation = false; } return instance; } public function SingletonDemo():void { if (!allowInstantiation) { throw new Error("Error: Instantiation failed: Use SingletonDemo.getInstance() instead of new."); } } } }This approach works very well and the implementation seems relatively clean to me. It will throw a run-time error if you try to instantiate the class directly, and will return null if you use try/catch to circumvent the error. The main disadvantage is that it does not generate compile time errors.
Claus Wahlers pointed me to another approach that was documented on the Kiwi Project blog. This approach takes advantage of the fact that you can define private classes outside of the package declaration, and use them as a "key" to control instantiation.
package {
public class SingletonDemo {
private static var instance:SingletonDemo;
public static function getInstance():SingletonDemo {
if (instance == null) {
instance = new SingletonDemo(new SingletonBlocker());
}
return instance;
}
public function SingletonDemo(p_key:SingletonBlocker):void {
// this shouldn't be necessary unless they fake out the compiler:
if (p_key == null) {
throw new Error("Error: Instantiation failed: Use SingletonDemo.getInstance() instead of new.");
}
}
}
}
// the following code is also in the SingletonDemo.as file
// this class is only available to SingletonDemo
// (despite the internal access designation)
internal class SingletonBlocker {}
This second solution feels a little more hackish to me, and I'm not completely certain whether this private class feature is officially supported. However, if you need compile-time errors, it's the way to go.
Both solutions also break down if you try to extend the class, as the constructor will be called when the subclass is instantiated. Extending Singletons is fairly rare, but if you need to do it, I'd recommend modifying the first solution (the second solution simply won't work for inheritance).
Comments (27)
We use approach #2. It has worked well enough, but of course you're right that it would be better to have private constructors.
I'm not sure what purpose the "internal" keyword serves on the SingletonBlocker class, since the class is only available within the file in which it is defined. I think it's redundant -- we don't use it, at any rate.
Posted by: David Coletta at July 12, 2006 03:11 PMURL: http://www.colettas.org
Another solution for singleton is proposed by zwetan on the FCNG google group (you can see it at the end of my comment).
I don't like that way for implement the singleton pattern. Personnally I prefer and use the first solution you submit, in most of case it's probably the best.
But instances are always created at start, not where they are needed, and we came back on the thorny problem of ressources management, if our singleton need to receive events, does it really needs to exist since application start ?
I prefer to have run time error during the developpement to detect when I'm wrong rather than having an 'hermétique' code.
///
text\Singleton.as
------
package test
{
public const Singleton:_Singleton = new _Singleton();
}
internal class _Singleton
{
function _Singleton()
{
}
public const testconst:String = "hello world";
public var testvar:String = "bonjour le monde";
public function testMethod():String
{
return "ni hao shijie";
}
}
------
testSingleton2.as
------
package
{
import flash.display.Sprite;
import test.Singleton;
public class testSingleton2 extends Sprite
{
public function testSingleton2()
{
trace( Singleton.testconst );
trace( Singleton.testvar );
trace( Singleton.testMethod() );
}
}
Posted by: Cédric Néhémie at July 12, 2006 03:15 PM}
///
URL: http://book.abe.free.fr
What is the advantage of using a Singleton over a static class?
Posted by: jerry hamby at July 12, 2006 03:22 PMURL:
Jerry,
Very good question. It actually made me focus on rationale instead of implementation, and reconsider how to implement both approaches.
Singleton resolves issues related to initialization order. If MyStaticClass has an initialization dependency on MyClass, I have no way to ensure that it initializes after MyClass? This can result in fairly randomly occurring problems (that are a pain in the arse to debug).
Singleton also allows for deferred instantiation (ie. you do not create the resource until you need it), and allows you to change the number of instances in the future without re-writing dependent classes.
My original examples did not facilitate the first two points, I have updated them to use deferred instantiation to fix it.
Posted by: Grant Skinner at July 12, 2006 03:50 PMURL: http://gskinner.com/
"What is the advantage of using a Singleton over a static class?"
For starters, not having to make every single method and property static.
Posted by: Keith Peters at July 12, 2006 03:52 PMURL: http://www.bit-101.com
here's another way:
use a private class (as described in method #2) as the actual class you want the singleton to be an instance of, then create an interface that all clients of the singleton use as the data type and make the private class implement that interface, then use the public class to create an instance of the private class and return it. Clients will find it impossible to create an instance of the singleton class as its actually kind of private and can only be instantiated from within the public class, any client that creates an instance of the public class directly will get compiler errors as that class doesnt support the interface.
Posted by: chris jenkins at July 12, 2006 04:24 PMURL:
I disagree that #2 looks hackish. Although it prevents subclassing, it comes closest to the traditional implementation of Singletons (private constructor: instantiation prevented at compile time). It can be a bitch to debug #1 especially if the malicious instantiation appears only once somewhere deep down the code and is executed rarely. I agree with David btw, i too think internal is redundant.
Posted by: Claus Wahlers at July 12, 2006 06:32 PMURL: http://wahlers.com.br/claus/blog/
Claus,
I was referring to the implementation, not the results. Using a (afaik) undocumented behaviour, and generating class definitions purely to act as a key to instantation seems a trifle more hack-y than an if statement.
Internal is redundant, but so is a semi-colon at the end of each line. I suppose in this instance it might actually be confusing because it doesn't act as an internal class, it acts like a private one - point taken on those grounds. :)
Posted by: Grant Skinner at July 12, 2006 08:50 PMURL: http://gskinner.com/
See, I think namespaces should handle this. They seem perfectly made for such an occasion. Only you can't use namespaces on constructors. Sigh.
Posted by: Max at July 12, 2006 10:11 PMURL:
Hi Grant,
This is a very interesting post but I think there are a couple things that need to be pointed out. I think what you are really referring to in this instance is the creation of abstract classes. This feature was completely allowed in Actionscript 2.0 by making the constructor a private member of the class. I must admit I was a little surprised at Adobe for not including the 'abstract' modifier but I guess they have their reasons. Unfortunately, like you mentioned above, Adobe removed that option and did not really give an option to create abstract classes. However I think there might be a way that does not include the aforementioned examples.
for example...
class abstractDimension
{
protected width:int;
protected height:int;
public function abstractDimension() {};
}
In this case we've created a class that proves useless upon instantiation. Is it a true abstract class? No, but it's real close. The main characteristic of abstract classes is that they are only useful of they are part of an inheritance chain. The example above pretty much takes care of enforcing that characteristic. Since all of the members are protected accept for the constructor, the class proves useless if instantiated directly however it proves useful if part of an inheritance chain.
The second issue is with the singleton pattern. Implementing a private member does not necessarily implement the singleton pattern. The singleton pattern is used when an object can only be instantiated one time. If a request is made to instantiate a class that implements the singleton pattern a reference to the current instance of the singleton class is return( if an instance is not present than one is instantiated ). Personally, I believe that there isn't a real reason to use the singleton pattern in flash unless your developing in Flash Lite or pocket PC Flash. My personal experience has been that the singleton pattern is used when resources are scarce and must be carefully used like in embedded systems. In most cases a static class (which is technically a type of singleton) should suffice. As for implementing the Singleton pattern in AS3 I believe that using any factory pattern should allow you to implement the Singleton pattern without a hitch!
Posted by: Samuel Agesilas at July 13, 2006 02:38 AMURL: http://www.levelofindustry.com
One thing that I forgot too mention, is that the first example posted is actually not a hack but a very close implementation of the singleton pattern... however I believe we can simplify the implementation like so...
package
{
public class SingletonDemo
{
private static var instance:SingletonDemo = null;
public function SingletonDemo()
{
if(SingletonDemo.instance != null)
{
throw new ArgumentError();
}
else
{
SingletonDemo.instance = this;
}
}
}
}
One thing I should mention is that checking for a created instance is done with more accuracy and less room for error by using reflection. In AS2 it would be something like this
if ( SingletonDemo.instance.__proto__ == SingleDemo.prototype )
this is ensures type safety while using the singleton pattern. In AS3 I believe the describeType method should be using for runtime type checking. Anyway for the sake of argument I too used the null check in my example.
Posted by: Samuel Agesilas at July 13, 2006 04:40 AMURL: http://www.levelofindustry.com
Samuel,
Thanks for your comments. This article definitely focused on Singleton, not abstract classes (which of course also suffer from the lack of protected constructors in AS3). As I mentioned in the article "Both solutions also break down if you try to extend the class", which renders them useless for abstract classes.
If you look at my comment above, I explain some of the advantages of a Singleton over static classes.
Your variation on the Singleton pattern suffers from a couple of flaws. Firstly, it creates unpredictable results from any specific context, as you have no way to know before attempting instantiation if it will fail, and no way to gain access to the instance if it does fail. Secondly, it does not provide for the same level of abstraction that my original approaches do.
Singleton is a factory pattern, and should be treated as such, with a construction method that abstracts instantiation. The public interface for Singleton in ECMA languages is quite widely accepted (ie. getInstance), and I don't think there's any reason to change that.
Cheers.
Posted by: Grant Skinner at July 13, 2006 09:45 AMURL: http://gskinner.com/
Grant,
Your absolutely right about my example! I actually goofed pasting the wrong code. LOL ( that's what happens when u post at 5 am. :D ) Anyway here's the right code.
package
{
import flash.utils.*;
public class SingletonDemo
{
private static var instance:SingletonDemo = null;
private static var allowInstantiation:Boolean = false;
public static function getInstance() : SingletonDemo
{
if ( SingletonDemo.instance == null )
{
SingletonDemo.allowInstantiation = true;
SingletonDemo.instance = new SingletonDemo();
SingletonDemo.allowInstantiation = false;
}
return SingletonDemo.instance;
}
public function SingletonDemo()
{
if ( getQualifiedClassName(super) == "SingletonDemo" )
{
if (!allowInstantiation)
{
throw new Error("Error: Instantiation failed: Use SingletonDemo.getInstance() instead of new.");
}
}
}
}
}
In my method I allow for a Singleton instance to be created using a factory method and I restrict direct instantiation in the constructor but I allow it if it's part of an inheritance chain. Using reflection, I can emulate the protected constructor behavior in Actionscript 3.
Now as far as the use of Singleton's I still believe that Static classes should be use over singletons. If order of operations is a concern then the creation of a first responder ( ie Main static member of the application entry point ) will solve that.
e.g.
class myFlashApp
{
public static function main( argv:Array )
{
//Call static members in the desired order.
}
}
This method works extremely well in situations where a User Interface is being built. It's probably important to note that the use of singleton's should be regarded carefully since they are generally thread unsafe just like classes with static members. In flash , threads are something that we really don't have to worry that much about but they can become a nightmare in Java or C++. So I guess what I'm saying is that Singleton's should be considered only when you want to control the amount of instances that can be created of an object. In Actionscript, Order of instantiation should NOT be the sole reason why the Singleton Pattern should be used. If order of instantiation is the only consideration then I strongly suggest the use of static methods if and ONLY if the class that encapsulates the static methods will not be a part of an inheritance chain. So I guess we can agree to disagree on that point, however I don't think one is superior to the other, I just think it's more of a philosophical difference or a matter of opinion as to which method should be used.
ciao,
Posted by: Samuel Agesilas at July 13, 2006 01:27 PMsam
URL: http://www.levelofindustry.com
Keith you are total idiot re: the static comment.
There are very few reasons to use a singleton. Almost never. Use an init() method with your static classes.
This is just another example of you hacks inventing moronic work arounds.
IF A LANGUAGE DOES NOT DIRECTLY PROVIDE A WAY TO IMPLEMENT A PATTERN/IDIOM THEN DON'T USE IT.
Posted by: Ludwig Van at September 1, 2006 03:01 PMURL:
I know I'm a little late for this topic but...
To those that say singletons are useless in AS3 are just being close-minded. For one thing, design patterns are conventionalized tools designed as solutions to common problems. If its application to a framework is clean, effective, and strict, then it shouldn't matter whether its a static class or a singleton.
Also, there are many other differences between static classes and singletons that you aren't considering because of the simple fact that singletons are rarely necessary except for obscure situations. However such obscure situations CAN exist. Here's a few to name off:
1) A globally accessible instance that is independently executing logic.
In a case such as this, instantiation needs to occur. Sure you can probably link up event systems to static methods or whatever, but how do you intend to do that? Ok, a static init() class like Ludwig proposes. Now you have to check if the necessary preliminary steps have been performed for the class already, except since the class is static with every public method statically accessible, the init check needs to occur off EVERY public method.
2) Using a factory pattern to provide a globally accessible class to an instance of something on runtime.
Lets say you want 2 custom classes that lists constants for input char codes: One for a remote control and another for a cell phone, so your application can operate both on a mobile device and on your TV. In this case you want something static, yet your classes shouldn't concretely access them, since they shouldn't inherently know which one to access. Using a factory method, you can getInstance the one you want and pass it to your classes, which will be able to accept either one via polymorphism (assuming their constants are labeled the same).
Then there's always that whole deferred instantiation thing...
Posted by: Steve Schelter at October 16, 2006 06:43 PMURL: http://www.schelterstudios.com
Re: Singletons vs static classes
First of all, static classes are very un-OO, basically functions defined in a namespace, and you will end up with lots of problems if you use such solutions (as mentioned by comments above).
Something rarely mentioned when talking about singletons is that guarantee that there will only be one instance of a class is not necessarily something client code (code that uses the singleton class) needs to know about. Apart from retrieving the instance, all code using the singleton object can and should act upon it as if it was any ordinary object, because a later version of the class may allow multiple instances, for example.
I usually use the singleton pattern when I have a resource that I want to regulate access to, a connection, a state handler, a cache or something like that. I make it a singleton because I want to have a single point of access, regardless of which part of the application that needs it.
What I don't do is litter my code with SingletonClass.getInstance() calls, but pass the singleton around as I would any other object. I do this because I know that in the future the resource may change, perhaps I switch implementation, perhaps the resource itself changes in a way that makes multiple access points desirable. If it does change in this way, I want to allow more than one instance of my singleton class (which means that it will no longer be a singleton). The only thing I have to do now is either change the few cases where I retrieve the singleton or the getInstance method so that it returns a new copy for each call (or a copy from a pool or some other appropriate technique). The rest of the code (and other peoples code that relies on mine) doesn't have to change one bit.
Fair enough, changing the getInstance method means that it doesn't matter if your code contains lots of SingletonClass.getInstance() calls, but don't count on that solution to be the appropriate solution.
By using singleton instances as any other object you don't fall into the bad smell of using singletons as global variables. A quick googling on "singleton problems" or "singleton smell" will tell you why that's a bad idea. Moreover, using singletons in this way is very much more useful than the static class solution, which quickly shows its limits.
Posted by: Theo at October 24, 2006 02:34 PMURL: http://blog.iconara.net
Putting aside subjective arguments to the merits/demerits of Singletons...
[code]
public class Singleton
{
private static var instance : Singleton;
public static function getInstance() : Singleton
{
if ( instance == null )
instance = new Singleton( arguments.callee );
return instance;
}
public function Singleton( caller : Function = null )
{
if( caller != Singleton.getInstance )
throw new Error ("Singleton is a singleton class, use Singleton.getInstance() instead");
if ( Singleton.singleton != null )
throw new Error( "Singleton broke instantiation limit" );
// }
}
[/code]
Posted by: alinear at March 6, 2007 03:16 AMURL: http://alinear.net
I noticed that in your examples the constructors return void. I have gotten in the habit of never putting a return type on constructors, and noticed that AS class code generated in Flex Builder 2.0.1 does not do this either. Is this something specific to a singleton?
Do you have any insight on this?
Posted by: Mugur Marculescu at March 25, 2007 04:30 PMThanks for sharing your examples.
URL: http://www.mugur.com
alinear, thanks for posting that.
couple of questions... 4th to last line, should that read "if ( Singleton.instance != null )" as opposed to "if ( Singleton.singleton != null )"?
also, the //} is a typo, correct?
Posted by: taber at May 20, 2007 06:13 PMURL:
package{
public class SingletonDemo extends Sprite{
private static var _instance:SingletonDemo;
public function SingletonDemo():void{
if (_instance)
throw new Error("Error: "+this+" already exists. You can access is with getInstance();");
_instance = this;
//set up your constructor here
Posted by: BS at June 8, 2007 06:06 PM}
public static function getInstance():SingletonDemo{
if (!_instance)
_instance = new SingletonDemo();
return _instance;
}
}
}
URL: http://theillustratedlife.com
Looks like my original comment went away. The above example allows Singletons to be instantiated by dropping Library items onto the stage.
BTW, your comments need an edit button. =)
Posted by: BS at June 8, 2007 06:18 PMURL: http://theillustratedlife.com
Yes sorry for the typos. I typically do this method (below). It isn't perfect, but whatever floats your boat. I don't think I like using the above key access style or the private class one myself.
public class Singleton
{
private static var instance:Singleton;
public function Singleton(caller:Function = null)
{
if (caller != Singleton.getInstance)
{
// }
if (Singleton.instance != null)
{
// }
}
public static function getInstance():Singleton
{
if (Singleton.instance == null)
{
Singleton.instance = new Singleton(arguments.callee);
}
return instance;
}
}
That SHOULD be copy/paste friendly...
Posted by: alinear at July 5, 2007 10:42 PMURL: http://alinear.net
Take a look at this....
Posted by: WebSurfer at January 8, 2008 11:04 AMhttp://www.cmd.tech.nhl.nl/users/groot406/weblog/?p=43
URL:
I'm using a Singleton class in my project to provide a menu drop down list when buttons are clicked (i.e. Menu, Edit, View, etc). As only one instance is allowed it works quite well as when each menu button is clicked the respective drop down appears and the previously displayed drop down disappears. However, how do I remove a Singleton class from the display list once one of the items in the drop down has been selected?
Posted by: taramouse at February 11, 2008 06:10 PMURL:
Isn't this the easiest way?
package {
Posted by: szataniol at April 9, 2008 03:09 AMpublic class Singleton() {
private static var instance:Singleton
}
public static function getInstance():Singleton {
return instance || (instance = new Singleton())
}
}
URL:
I like the use of the SingetonEnforcer class in the Singleton constructor because as we have all learned it gives us compile time error checking and makes it impossible to *accidentally* instantiate the Singleton class.
One thing though, I am finding myself re-pasting the basic Singleton constructs over and over.
Grant, do you think it is possible to create a base class for Singletons when using the Singleton Enforcer (or hopefully someday a private constructor)?
Thanks...
Posted by: Shanimal at June 17, 2008 01:18 PMURL: http://shanimal.com/
Here's a graceful solution to singletons, allowing extendable singletons as well.
http://blog.guttershark.net/?p=16
-Aaron
Posted by: Aaron Smith at July 25, 2008 01:34 AMURL: http://www.guttershark.net