A better AS3 Singleton implementation

As a developer we usually need to create libraries to reuse in various projects, most of them are of the manager style : one class (or instance) to handle all in coming tasks from various places, popular examples are : Tween engines, Loading services, 3D libraries, Sound processing library … The simplest implementation is the static-class-methods way.

I. THE STATIC CLASS METHODS IMPLEMENTATION :

Let’s have a look through a simple library class :

package {
	public class MyUtility {
		public static function methodA(): void {
			//do A things here
		}
		public static function methodB(): void {
			//do B things here
		}
	}
}

And its simple usage syntax

MyUtility.methodA();//call method A
MyUtility.methodB();//call method B


This approach, though very clear and simple, in both implementation and usage introduces several problems :

  1. Memory cost : Static class members will need memory to store all the data, just as class instances, the problem is, the memory got allocated by static class should never be disposed, as its method can be called any time from various places in your (or other guy’s ) code. How can we be able to clear references to static methods of a class ? We can’t. This single factor will degrade our application dramatically over time, as modules get loaded, more and more static classes being deployed got stuck in the memory, and memory footprint raised up.
  2. Modules file size : all class libraries got compiled into every modules used them, that means there might be many library duplication over modules, of course, it’s not very efficient if the size of library is big or you are using a lot of static libraries – you force users waiting for things you already have, to be loaded again and again.
  3. Rigid binding between these libraries : this will not only disable the ability to unit test them, but also, disable developer to change the dependent libraries later on. Let’s say, if we have a Transition library TransA that got to use a tween engine TweenA then if we are referencing TweenA directly from TransA, TransA will never be able to live without TweenA. That say, if user want to use TransA with some other TweenB engine, he just can’t do that without modify TransA heavily. That’s bad, strong coupling like this is very bad practice and needless to say, we must avoid it.

There is also another popular library implementation : Singleton.

II. THE POPULAR AS3 SINGLETON IMPLEMENTATION :

Basically singleton is just as simple as “prevent user to instantiate a Class and use the only one instance provided instead”. Let’s have a look through the most popular singleton implementation in AS3.

package {
	public class MyUtility {
		function methodA(): void;
		function methodB(): void;

		public function MyUtility(){
			if (_instance) throw
				new Error("MyUtility is singleton and can not be instantiated !");
		}

		protected var _instance : MyUtility = new MyUtility();
		public static function getInstance(): MyUtility { return _instance; }
//you can also change the static function getInstance() to a getter instance for shorter syntax, but the getInstance() is more popular as from my awareness ...
	}
}

Ok, for perfectionist : this is NOT the perfect singleton implementation, yet, as user can still instantiate the class by using try / catch. But it’s non sense fighting for the perfect version as developers won’t use our library just for breaking purpose. As long as they can’t instantiate, they will know it’s singleton and use .getInstance(), that’s enough… Think ! Don’t put your-smart-codes in just to make the library more complex. There are no need for any kind of SingletonEnforcer or secretKey here.

What’s good here is that MyUtility now has only one static method (and one variable) to keep reference to an instance of MyUtility and as long as we want to dispose the Utility we can dispose the only _instance and get back the memory cost (but i don’t see that it will happen very often).

What’s bad here is the usage syntax :

MyUtility.getInstance().methodA();
MyUtility.getInstance().methodB();

Why should i need to .getInstance() all the time ? If there are only one thing to choose from, why should we need to choose? Hey, we don’t need to type that !

Other bad things like module file size cost and rigid binding is still remains.This implementation only solves one problem (memory cost) while introduces another one (stupid syntax).

That’s why you are being told that static is bad and devil and you should keep away from it. Well, i don’t really think that we should keep away from it, but just be careful when it comes to static cases. Static is a language feature, it’s exist for some reasons but it matters how you used it, so again, be careful !

III. A BETTER WAY AROUND :

First thought comes to our mind is that we need to implement an Interface to have Strong typing and smaller file size for modules, basically, modules will only have reference to the Interface instead of the implementation class, the implementation classes will only get compiled into main module. We modify the Singleton a little bit to implements IMyUtility !

package {//first, the interface
	public interface IMyUtility {
		function methodA(): IMyUtility;
		function methodB(): IMyUtility;
	}
}
package {//second, the class implementation
	internal class MyUtilityCore implements IMyUtility {
		public function methodA(): IMyUtility {};
		public function methodB(): IMyUtility {};
	}
}

At this point we have a normal class library implementation with with the present of an interface. You may have noticed that we now have a better jQuery style syntax where methods can be chained. The MyUtilityCore class is now internal, completely prevent users to accidentally instantiate it.

To prevent the heavy MyUtilityCore class gets into the compiled modules, we make another two classes, one for modules to get access to MyUtilityCore functionalities through IMyUtility interface, one for main module to initialize (do inject MyUtilityCore implementation to MyUtility). Here is the simplest version !

package {//fourth, the initialize package function
	public var myUtility : IMyUtility; /* [GETTER] don't change this variable ! */
}
package {//fourth, the initialize package function
	public function initMyUtility(): IMyUtility {
		if (!myUtility) myUtility = new MyUtilityCore();
		return myUtility;
	}
}

For simplicity purpose we don’t want to force myUtility to be a getter as it should be (in that case, we will need another internal class to save the reference to the MyUtilityCore instance because we can not declare a package variable together with a package function in the same file). Make a caution for our developers, that’s enough.

Let’s see what we have up to now. We need to init MyUtility before use, call it only once from the main Module, where the MyUtilityCore class got injected :

initMyUtility();//only call once in the main module

And for each modules, the usage is just the same as the static class method implementation (well, actually a bit better with j-Query chain) :

//use extensively in modules
myUtility.methodA()//call method A
		.methodB();//then call method B

As a brief  conclusion about this implementation :

  1. We replace one heavy class (MyUtilityCore) in modules by several lightweight one (myUtility, IMyUtility) to minimize file size in modules.
  2. We may keep memory low by disposing the only the instance of MyUtilityCore at anytime by setting myUtility = null.
  3. We prevent the rigid classes binding by using interface, later on, if user don’t like our myUtilityCore implementation they can change to another one without worring about code overlaps / fightings.
  4. We will need to write more code for each library as there are now 4 instead of just one class. The implementation is a bit more complex, but for me, as long as the result looks best to our users, it’s worth implemeting this !

And that’s it – A better AS3 Singleton implementation. If you have any idea about improving this implementation or a better way doing it, don’t hesitate to raise up your voice, we are all ears listening !

You can also download the sample code FD project 

Advertisements

One thought on “A better AS3 Singleton implementation

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