Implement a true Singleton in AS3

Singleton is a design pattern that enforces that a class can have only one instance which is shared by all and provides an easy global access point to this. A few examples are:

  • In iOS the UIDevice class is a singleton which provides information about the device like its unique ID. Obviously there is not more than one device.
  • Every application running in iOS must have a single instance of UIApplication class. Naturally that is a Singleton.
  • In a game generally there is one single GameControl object which manages the main game loop. If someone can create more than one game control and can run the main loop more than once, it can damage a lot.
  • Several design patterns like Abstract Factory, Flyweight uses Singleton in their implementation.

Although Singleton provides a global access, it have two benefits over using global variable. First, it does not pollute the global name space and second, it can be lazy initialized i.e. unlike global variables it can be instantiated only when it is required.

Okay, that’s enough talking. Let’s see how we can implement a Singleton in AS3.

package
{
    public class Singleton
    {
        private static var _instance:Singleton = null;

        public function Singleton()
        {
        }

        public static function sharedInstance():Singleton {
            if (_instance == null) {
                _instance = new Singleton();
            }

            return _instance;
        }
    }
}

This is the most straight forward way to implement a Singleton. First we declare a private static variable _instance in Singleton class and then create a public static method sharedInstace(). In sharedInstance() we check whether _instance is null or not. If it is null, then sharedInstance() is called for the first time. So we instantiate the instance of Singleton. Any further call to sharedInstance() will return the _instance created earlier, instead of creating a new one. As a result every call to sharedInstance() returns the same instance.

We can test this easily.

var a:Singleton = Singleton.sharedInstance();
var b:Singleton = Singleton.sharedInstance();

if (a == b) {
    trace("a and b are same");
} else {
    trace("a and b are not same");
}

Output is naturally a and b are same.

Note that Singleton.sharedInstance() is the global access point to the shared instance that the Singleton is supposed to provide. And also the instance is not created unless sharedInstance() is called, unlike a global variable.

But we have a little problem here. Calling to sharedInstance() will return the shared _instance, but Singleton class does not prevent to create new objects of it. In fact it is fairly easy to create a new Singleton object which is not shared, something that should be enforced by the Singleton pattern.

var c:Singleton = new Singleton();
var d:Singleton = new Singleton();

if (c == d) {
    trace("c and d are same");
} else {
    trace("c and d are not same");
}

Naturally c and d are not same.

The solution of this is to make the constructor of Singleton non-public so that new Singleton() is no longer valid.

private function Singleton()
{
}

And opps, the compiler have problem with this. It is saying “A constructor can only be declared public”. Now we have a big problem. Making the constructor non-public is the approach taken by most of the languages like C++ or Java, but AS3 does NOT support non-public constructor. So in AS3 we cannot prevent the creation of Singleton object in this way. This poses the real difficulty of implementing a true Singleton in AS3.

A few approaches, all equally weird, are available to prevent the creation. Personally I like the following.

public class Singleton
{
    private static var _instance:Singleton = null;

    public function Singleton(caller:Function = null)
    {
        if (caller != preventCreation) {
            throw new Error("Creation of Singleton without calling sharedInstance is not valid");
        }
    }

    private static function preventCreation():void {
    }

    public static function sharedInstance():Singleton {
        if (_instance == null) {
            _instance = new Singleton(preventCreation);
        }

        return _instance;
    }
}

A private static method preventCreation (I wanted to name it weirdMethod) is defined and it is passed to the constructor from sharedInstance. The constructor compares the caller and throws a run time error if the caller is not preventCreation. As preventCreation is private, it is not available outside. So trying to do new Singleton() from outside will fail in run time. However, this method does not force compile time prevention.

The whole demo project can be downloaded from here.

And now some final ending notes:

  • Singleton can be generalized to create ‘n’ number of objects instead of creating 1. But that is not as common as the single instance version where n = 1.
  • Before creating a Singleton make sure that a singleton is really needed. There is a huge debate on whether Singleton should be used or not, and there are people who consider Singleton as an anti-pattern. Those discussions are beyond the scope of this current writing, neither they are specific to AS3. May be in future I will write about that too, but for now check Why Singletons are Evil and Singleton: How should it be used.
  • For a better understanding of Singleton check Design Patterns book by GoF and Wikipedia entry for Singleton.
  • There are other ways, possibly better, to implement Singleton in AS3. Check Singleton Pattern in AS3 which explains another way and discusses two common mistakes.

As always, any feedback and/or suggestion is welcome.

Update: Even this process of creating Singleton can be broken by extending Singleton as explained here. Thanks to Krilnon for pointing this out.

Advertisements
This entry was posted in AS3, Design Pattern and tagged , . Bookmark the permalink.

6 Responses to Implement a true Singleton in AS3

  1. Topu says:

    Great Start Taskin! liked the Article.

    Another quick and simple (and weired!) implementation of singletone in AS3 can be:

    private static var _instance:AliveEngine = new AliveEngine();

    public function AliveEngine():void
    {
    if(instance)
    {
    throw new Error (“We cannot create a new instance of this class.
    Please use AliveEngine.getSharedInstance()”);
    }
    }

    public static function getSharedInstance():AliveEngine
    {
    return _instance;
    }

  2. Awesome article.

    I’m working on a game with different classes. I want that when I click, for instance, go to main menu button, take me there.

    I implemented the singleton pattern and so far so good. The thing is that I can call a function from the main menu class but not it’s constructor (file is MainMenu.as) what can I do to call it?

    Thanks so much !!

    • taskinoor says:

      Sorry I could not understand your problem fully. Can you explain the problem a little bit more?

      • Sure taskinoor, let me explain it a little more.

        I created many classes for the game, f.i. MainMenu.as , GameObjects.as , GameStart.as , Store.as , Statistics.as and so on.

        The game has a main menu (MainMenu.as file), where you choose the mission you want to play. If you haven’t play it before, you can only choose mission 1.

        When I’m on GameStart, I’m calling many functions and files to make the game happend. When you finish a mission (mission 1), I change a global var inside Statistics.as called currentMission to “Mission2”.

        So far so good. The thing is that when you finish mission 1I want to have a button that takes me again to the MainMenu.as but with the new “Mission2” var (so it will be available to select mission 2). I can’t call the MainMenu constructor, so I created an singleton pattern.

        And I did it pretty much like your example. It works great, but only if I call another function from the MainMenu class that is not the constructor, , but I want to call the constructor because that’s where I have all the thing. Can it be possible?

        Other thing that I though was copy all the code inside the MainMenu.as constructor to another function and call that one instead of the constructor.

        Any suggestion? Thanks so much for your time and please let me know if I was very clear with the explanation !!

        Happy day !!

      • Hey Taskinoor.

        I already solved the problem. The thing is that you can’t have an instance of the constructor of the class. You just have to create another function outside the constructor to have the singleton to work. This might be for other programming languages.

        Thanks so much for your time !!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s