Singletons in AS3

With the introduction of Actionscript 3 there was a lot of discussion about how to implement the singleton design pattern. This happened because Actionscript 3 doesn’t allow private or protected constructors and this prevents the most common implementation technique for singletons. A number of solutions have been proposed, just do a search on Google to find them, or check out Grant Skinner’s website for two good examples.

At the time, this seemed to be a major faux pas by Adobe and considering the noise generated one would have been forgiven for thinking it’s not possible to write software these days without using singletons. But singletons are never actually needed and are rarely a good idea.

Bad Singletons

The singleton pattern was described in the book “Design Patterns, Elements of Reusable Object-Oriented Software”, commonly called the Gang of Four book. In this book the intent of the singleton pattern is described as to “ensure a class only has one instance, and provide a global point to access it”.

I was first introduced to the singleton pattern as an alternative to global variables (”global variables are bad, use a singleton instead”). But this is one instance where singletons emphatically should not be used. Replacing a global variable with a singleton is just a lazy way of avoiding global variables without avoiding any of the problems inherent in global variables.

To summarise some of the problems global variables cause –

  • Inadvertent changes can occur – You may change the value of a global variable in one place and then think that it has remained unchanged elsewhere.
  • Multiple references to the one object – You may refer to the same value by two names and not realise they’re the same variable. For example, if you pass the global into a function the one variable now has two ways to reference it, by the argument name and by the global name. Your function may assume the two are different.
  • Inhibit code reuse – Classes that depend on the global variable can only be used in applications where the global variable exists (and uses the same variable name).
  • Break modularity – All classes that use the global data are inherently tightly coupled since they all depend on what the other classes do with the global data.
  • Make testing difficult – Try persuading a class to use a mock object instead of the global without changing the code in the class.

What may be surprising is that all these problems exist with singletons as well because the singleton has a “global point of access”. While the first two problems can be avoided by being very careful, the others are inherent in the use of globals and singletons and so can’t be avoided.

Alternatives to Singletons

A singleton is responsible for both its behaviour and for ensuring that only one instance of it exists. In other words, it is responsible for two unconnected activities. This should usually be avoided and the unconnected activities should be implemented in different classes.

In many cases where singletons are used, there’s nothing inherent in the singleton class that means only one instance should exist. Rather, it’s a requirement (or merely a useful feature) for the application that only one instance should exist. If the application wants there to be only one instance, then the application should enforce this behaviour not the class. This way the class itself can be used in other applications where multiple instances are desirable.

To accomplish this, create the class as a normal, non-singleton, class and enforce the single-instance only behaviour elsewhere in the application. If you want a global point of access (the problems with globals described above will still occur), then you could use a factory to create the instance and reuse it in any code that requests it. If you don’t want the global point of access then you could create a single instance and pass it as an argument to all the classes and methods that need it.

But what if it is an inherent feature of the class that only one instance should exist? For example, if multiple instances would break the functionality. Then the class should be responsible for ensuring the single instance behaviour. But even then the best answer may not be the singleton pattern.

Sometimes the single instance requirement is because there’s one or more properties within the class that shouldn’t be duplicated. In this case, the particular properties could be created as static class properties and used by all instances of the class. This is an example of the monostate pattern.

package { public class Monostate { private static var _mono:SomeClass = null; public function get mono():SomeObj { if( _mono == null ) { _mono = new SomeClass(); } return _mono; } } }

In general, the monostate pattern uses private static properties to ensure that every instance of the class has the same state and uses public accessors to those properties. In some cases only some properties will need to be the same across instances while in others all properties need to be the same. Either way, the singular properties are created as static variables within the class.

The class is instantiated and used as normal, and may be extended via inheritance. Importantly, the client classes that use this class don’t need to know that state is shared across all instances – this behaviour and the knowledge about it is internal to the class only.

Good Singletons

There may still be some circumstances where it is important that one and only one instance of a class should exist and this behaviour is inherent to the class itself rather than being a feature of the application being developed. In such cases the singleton pattern is appropriate, but they are few and you should bear in mind the potential problems outlined above.

Consider also that some of these problems with the singleton (and other globals) can be reduced or eliminated if the client classes using the singleton do so in such a way that they can not be affected by the actions of other classes in relation to the singleton, in particular if the singleton is designed for write access only (e.g. a logging class) or for read access only (e.g. a configuration data class) then the classes using the singleton are not coupled to each other since they are unaffected by each others use of the singleton. They are, obviously, still coupled to the singleton itself.

Conclusion

  • The singleton pattern should not be used when it’s merely important for the application to have only one instance of the class (the application should simply create only one instance).
  • The singleton pattern should not be used when it’s important for the class to have only one instance of one or more properties within it (the class should use static properties as in the monostate state pattern).
  • The singleton pattern should not be used when it’s important for an instance to be globally accessible (use a factory to manage access to the one (or more) instances of the class).
  • The singleton pattern should be used when it’s important for the class to have exactly one instance.

The singleton pattern is often one of the first design patterns that a developer learns. I think this is a mistake since the pattern is so easily and frequently abused. Since deciding to consider the alternatives before using singletons in my code I find I’ve not used any singletons in over a year and my code has been more modular, more reusable and easier to test as a result.