gSkinner - Home

AS3: Singletons

Posted on July 12, 2006 by Grant Skinner

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).

Follow @gskinner on Twitter for more news and views on interactive media.
43 Comments

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 on Jul 12, 2006 3:11pm URL: 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 on Jul 12, 2006 3:15pm URL: http://book.abe.free.fr

What is the advantage of using a Singleton over a static class?

Posted by: jerry hamby on Jul 12, 2006 3:22pm

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 on Jul 12, 2006 3:50pm URL: 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 on Jul 12, 2006 3:52pm URL: 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 on Jul 12, 2006 4:24pm

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 on Jul 12, 2006 6:32pm URL: 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 on Jul 12, 2006 8:50pm URL: 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 on Jul 12, 2006 10:11pm

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 on Jul 13, 2006 2:38am URL: 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 on Jul 13, 2006 4:40am URL: 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 on Jul 13, 2006 9:45am URL: 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,

sam

Posted by: Samuel Agesilas on Jul 13, 2006 1:27pm 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 on Sep 1, 2006 3:01pm

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 on Oct 16, 2006 6:43pm URL: 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 on Oct 24, 2006 2:34pm URL: 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" );

//

Posted by: alinear on Mar 6, 2007 3:16am URL: 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?

Thanks for sharing your examples.

Posted by: Mugur Marculescu on Mar 25, 2007 4:30pm 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 on May 20, 2007 6:13pm

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

}

public static function getInstance():SingletonDemo{

if (!_instance)

_instance = new SingletonDemo();

return _instance;

}

}

}

Posted by: BS on Jun 8, 2007 6:06pm 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 on Jun 8, 2007 6:18pm URL: 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)

{

//

Posted by: alinear on Jul 5, 2007 10:42pm URL: http://alinear.net

Take a look at this....

http://www.cmd.tech.nhl.nl/users/groot406/weblog/?p=43

Posted by: WebSurfer on Jan 8, 2008 11:04am

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 on Feb 11, 2008 6:10pm

Isn't this the easiest way?

package {

public class Singleton() {

private static var instance:Singleton

}

public static function getInstance():Singleton {

return instance || (instance = new Singleton())

}

}

Posted by: szataniol on Apr 9, 2008 3:09am

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 on Jun 17, 2008 1:18pm URL: 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 on Jul 25, 2008 1:34am URL: http://www.guttershark.net

Here is what I found to extend a Singleton, I thought it might be interesting to mention it here:

http://www.soundstep.com/blog/2008/11/01/extend-a-singleton/

Romu

Posted by: Romu on Nov 1, 2008 1:19pm URL: http://www.soundstep.com/

THANKS Grant!!!.

Tried several other 'tutorials' on the web but none of them worked. I'll study this.

tf

Posted by: tony fraser on Dec 28, 2008 9:39pm

Hi! Is there a way to transform a Document Class in a Singleton?

Posted by: Luca on Jul 14, 2009 7:23am URL: http://reghellin.com

"What is the advantage of using a Singleton over a static class?"

Good question. Questions like this means you're thinking about this.

The question pinpoints exactly what you don't understand - The problem that led to this pattern. The problem is that we need the object to change over time (thus not having static attributes and methods), AND at the same time we must only allow 1 instance of this object to exist.

A concrete example will help. Imagine you are making a chess game. The game will have a class called Board. Pieces need to talk to the Board to get information about where the other pieces are and perhaps even the size of the board etc. It would be impossible to create a new Board call everytime a Piece needs to communicate to the Board. Why? Because the new instance of Board will be brand new and not have the state of the game!

That is why singletons are needed, and in turn answers the question "What is the advantage of using a Singleton over a static class?"

Posted by: jack on Jul 18, 2009 6:04am

Hi Grant,

I'm using the first option of the solutions you provided but I can't seem to delete an object wich uses a singleton class. The delete action does return true but when I try to create a new object the instance is not null. Is this a singleton thing or am I doing something stupid?

Thanks btw

Posted by: Bart on Oct 21, 2009 6:17am

I've posted a similar structure on http://simplestexplanation.com/?p=126

I find it to be quite a bit simpler.

Posted by: Morgan Engel on Nov 24, 2009 11:33am URL: http://www.simplestexplanation.com

Morgan, your approach of using a constant is a lot tidier! Does anyone see any downfall from implementing the singleton pattern this way?

Posted by: Ant. on Dec 1, 2009 5:47am

szataniol is right.

Posted by: Ann Onymouse on Jan 19, 2010 2:44pm

Why do you need allowInstantiation variable?

Posted by: Ionel Crisu on Mar 7, 2010 10:21am URL: http://riaextended.com

@Luca, (even though your question was a million years ago), with a Doc class we can assume that the instance already exists once the movie is running. So make sure you Doc class has a static var of it's own type...

private static var instance:DocumentClass;

...Then set the instance in the constructor...

public function DocumentClass():void

{

instance = this;

// etc

}

...and then you can simplify the getInstance method...

public static function getInstance():DocumentClass {

return instance;

}

This should work in 99% of circumstances

Posted by: Rob on Apr 15, 2010 6:14am URL: http://www.unled.net/

Great Article. Why aren't offensive comments being deleted (Ludwig Van's and the one before me)?

Posted by: Filipe on Jun 8, 2011 9:15am

It wouldn't work if you use mxml to create an instance; For ex,



you will get a run-time error

Posted by: ozgur uksal on Jul 7, 2011 3:27pm

Thanks buddy

Posted by: Sathis Kumar Subramaniam on Sep 9, 2011 7:11pm

Is there something wrong with this approach?

package
{
import flash.utils.getQualifiedClassName;

public class SingletonExample
{
public static var instancesCount:int = 0;

public function SingletonExample()
{
if (instancesCount>0) {
trace('There can be only one instance of "' + getQualifiedClassName(this)+'" Class.');
}else {
instancesCount++;
}
}
}
}

Posted by: Pablo on Sep 30, 2011 9:54am

Though I would throw in another possible way of doing a singleton with a lazy load. Believe it would be the fastest way to ref the instance, but not sure.

It was inspired by Bill Pugh the Java Dude.


package {
/**
* @author actionscript
*/
public class Lazier {
public static function getInstance() : Lazier {
return SingletonHolderLazier.instance;
}

public function Lazier(s : SingletonEnforcer) {
if (s == null) throw new Error("Error: Instantiation failed: Use Lazier.getInstance() instead of new.");
}
}
}

internal class SingletonEnforcer {
}

internal class SingletonHolderLazier {
internal static var instance : Lazier = new Lazier(new SingletonEnforcer);
}


}
}

internal class SingletonEnforcer {
}

internal class SingletonHolderLazier {
internal static var instance : Lazier = new Lazier(new SingletonEnforcer);
}

Posted by: Tom Grant on Oct 14, 2011 1:59am URL: http://wgt.com

just add this to your class:

public static var instance:MyClass;
public static function getInstance():MyClass
{
return instance || (instance = new MyClass())
}

Posted by: mikeccuk2005 on Jun 28, 2012 9:38am

Leave a Reply

Your email is never published nor shared.




You may use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>