Singleton Pattern introduction

Staying on the course of my tutorial kick I’m now moving to the Singleton pattern. Understanding this pattern will help later in understanding patterns such as the Factory Pattern which I will be discussing later.

Another pattern, or rather anti-pattern according to some, is called the Singleton Pattern.

The Singleton pattern, as the name implies, allows for the use of one and only one object of a particular class. This pattern is a bit overused but it can be handy in some areas. For instance, a print spooler app may be a god reason to use this. Also, maybe a window manager, or facade, where, like the print spooler, there should only ever be one of these objects.

Sometimes you might also want to use this for storing global settings or some sort of data. Though it’s best to pass this data into your classes to keep them loosely coupled, sometimes you might just not have the time to do everything 100% correct and proper.

There are a couple different ways in which you can implement the Singleton Pattern depending on how you may want to utilize it. We’ll look at the first example as, let’s say, a print spooler.

We’ll place this in the “info/thaylin/singleton” package and call it “PrintSpoolerSingleton”.

package info.thaylin.singleton
{
	import flash.events.Event;
	
	public class PrintSpoolerSingleton
	{
		private static const INSTANCE:PrintSpoolerSingleton = new PrintSpoolerSingleton();
	    private var printer:PrinterClass = new PrinterClass();
	    private var jobs:Array = new Array();
	    
	    public function PrintSpoolerSingleton():void
	    {
	        if (INSTANCE != null)
	        {
	            //Flash forces constructors to be public
	            //An error is thrown to prevent any new instances from being created.
	            throw new Error("An instance of Singleton already exists.");
	        }
	        
	    }
	    public static function getInstance():PrintSpoolerSingleton
	    {
	        return INSTANCE;
	    }
	    public function addPrintJob(value:String):void
	    {
        	if(!printer.hasEventListener(PrinterClass.PRINTJOB_COMPLETE))
        	{
        		printer.addEventListener(PrinterClass.PRINTJOB_COMPLETE, printer_completeHandler);
        	}
    	    jobs.push(value);
    	    if(jobs.length == 1)
    	    {
	    	    printer.pushJob(value);	
    	    }
    	    trace('ADDING PRINT JOB '+value)
	    }
	    public function cancelLastPrintJob():void
	    {
	    	if( jobs.length > 1 )
	    	{
	    		jobs.pop();
	    	}
	    }
	    private function printer_completeHandler(event:Event):void
	    {
	    	trace('Printing complete for '+jobs.shift()+' |  Jobs remaining: '+jobs.length);
	    	
	    	
	    	if(jobs.length>0)
	    	{
	    		printer.pushJob(jobs[0]);
	    	}
	    }
	    
	}
}

And in case you would like to follow along here is that “PrinterClass” class within the “info/thaylin/singleton” folder as well.

package info.thaylin.singleton
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	public class PrinterClass extends EventDispatcher
	{
		private var timer:Timer = new Timer(3000, 1);
		public static const PRINTJOB_COMPLETE:String = 'printJobComplete';
		public static const PRINTJOB_STARTED:String = 'printJobStarted';
		public function PrinterClass(target:IEventDispatcher=null)
		{
			super(target);
			timer.addEventListener(TimerEvent.TIMER_COMPLETE, timer_completeHandler);
		}
		private function timer_completeHandler(event:TimerEvent):void
		{
			//IMAGINARY PRINTER HAS COMPLETED IT'S PRINTING JOB
			dispatchEvent(new Event(PRINTJOB_COMPLETE));
		}
		public function pushJob(value:Object):void
		{
			//PUSH A PRINT JOB TO OUR IMAGINARY PRINTER
			dispatchEvent(new Event(PRINTJOB_STARTED));
			timer.reset();
			timer.start();
		}
		
	}
}

The PrinterClass class is just our imaginary gateway to our imaginary printer. Here we just start a timer when a job is added and dispatch a completed event when the timer is complete to emulate the basic gist of a printer printing.

In the PrintSpoolerSingleton, we create an instance when the class is called for the first time. At that point there can be no more instances created. If a person were to try to create a new class with the new keyword it would throw the error in the constructor since that constant instance already exists. In other languages such as Java we would just make this a protected constructor which would then generate a compile time error as opposed to runtime error, but unfortunately, since flash does not currently support protected or private constructors, we’re forced to emulate it.

From there, we create a getInstance() method so we can retrieve the singular instance of the PrintSpooler, since there is only one printer being printed to.

Following that, we have our methods to talk to the printer, adding jobs to a queue of a jobs array, canceling the last added job and when a job is completed: pushing another job in the queue to the printer.

Now let’s test our work. First we’ll create a view class in which we’ll add a couple of buttons that will add and remove jobs from the printer queue. We’ll place this in the package “info/thaylin/views/” and call it “PrintScreenView”

package info.thaylin.views
{
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	
	import info.thaylin.singleton.PrintSpoolerSingleton;

	public class PrintScreenView extends Sprite
	{
		private var num:Number = 0;
		public function PrintScreenView(name:String)
		{
			super();
			this.name = name;
			init();
		}
		public function init():void
		{
			var addButton:Sprite = createButton(80, 40);
			addButton.addEventListener(MouseEvent.CLICK, addButton_clickHandler);
			
			var removeButton:Sprite = createButton(80, 40);
			removeButton.addEventListener(MouseEvent.CLICK, removeButton_clickHandler);
			addButton.x = 100;
			removeButton.x = 200;
			
			addChild(addButton);
			addChild(removeButton);
		}
		private function createButton(width:Number ,height:Number):Sprite
		{
			var shape:Sprite = new Sprite();
			shape.graphics.beginFill(0xFFCC00);
			shape.graphics.drawRect(0,0,width, height);
			shape.graphics.endFill();
			shape.buttonMode = true;
			return shape;
		}
		private function addButton_clickHandler(event:MouseEvent):void
		{
			var job:String = ('Job # '+(++num)+' ['+name+']');
			PrintSpoolerSingleton.getInstance().addPrintJob(job);
		}
		private function removeButton_clickHandler(event:MouseEvent):void
		{
			PrintSpoolerSingleton.getInstance().cancelLastPrintJob();
		}
		
	}
}

Now that we have this in a “view” type class we can create as many of these as we want on the stage. This is to give you a better idea of how our singleton will work. For this tutorial we’ll just create 2 of these view instances.

package {
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	
	import info.thaylin.singleton.PrintSpoolerSingleton;
	import info.thaylin.views.PrinterView;

	public class Main extends Sprite
	{
		
		public function Main()
		{
			var view1:PrinterView = new PrinterView('view1');
			var view2:PrinterView = new PrinterView('view2');
			
			view2.y = 50;
			addChild(view1);
			addChild(view2);
		}
		
	}
}

Now if you’ve been following along in your own project you can go ahead and test this. It’s not much for eye candy, but it’s just fine for demonstrating the Singleton. You’ll see 4 rectangles/buttons on your screen. The two left buttons add jobs to the print spooler queue, the ones on the right remove our last added job in the queue. As you click buttons and view the trace statements you’ll see our jobs being added, completed and removed. But, to really see the Singelton in action you’ll need to run the profiler if you’re using Flex Builder.

Right click on your main class and select “Profile As > Flex Application”. A window should come up prompting you for various things relating to the profiler. The default settings should be fine, just click resume.
In the Flex Profiling view you’ll see a Live Objects tab. This is what will show you how many instances of certain objects you have currently alive in memory and also a total since starting the app. You’ll notice that there is currently only one instance of the PrintSpoolerSingleton class, even though you have 2 PrinterView classes each calling the singleton. As you click about nothing will change from this. It will always remain one instance, no matter how many classes call it.
One thing you may also notice is that it never gets collected in trash since the class itself is referencing the instance and therefore negates being removed by the garbage collector.

While this can be good for quick referencing, you may not want something to persist in memory. If the class is a monster memory hog it would certainly not be good to keep it around wasting resources, so let’s see if we can remove the instance.

We’ll have to make some changes to our class so let’s go ahead and create a new class that’s similar to our old one. We’ll call it “PrintSpoolerSingletonRemovable” for lack of imagination on my part at the moment.

Here’s the code for our new Singleton class.

package info.thaylin.singleton
{
	import flash.events.Event;
	
	public class PrintSpoolerSingletonRemovable
	{
		private static var INSTANCE:PrintSpoolerSingletonRemovable;
	    	private static var printer:PrinterClass;
	    	private static var jobs:Array;
	    
	    	public function PrintSpoolerSingletonRemovable(enf:SingletonEnforcer):void
	    	{
		        if (enf == null)
		        {
		            //Flash forces constructors to be public
		            //An error is thrown to prevent any new instances from being created.
		            throw new Error("An instance of Singleton already exists.");
		        }
	        
	    	}
	    	public static function getInstance():PrintSpoolerSingletonRemovable
	    	{
	    		if(!INSTANCE)
	    		{
	    			INSTANCE = new PrintSpoolerSingletonRemovable( new SingletonEnforcer() );
	   				printer = new PrinterClass();
	    			jobs = new Array();
	    		}
	    	
	        	return INSTANCE;
	    	}
	    	public function addPrintJob(value:String):void
	    	{
	    		//MAKE SURE THE INSTANCE EXISTS SINCE THIS IS A PUBLICLY ACCESSIBLE FUNCTION
	    		if( getInstance() )
	    		{
	        		if(!printer.hasEventListener(PrinterClass.PRINTJOB_COMPLETE))
	        		{
	        			printer.addEventListener(PrinterClass.PRINTJOB_COMPLETE, printer_completeHandler);
	        		}
    	    		jobs.push(value);
    	    		if(jobs.length == 1)
					{
						printer.pushJob(value);
					}
    		    	trace('ADDING PRINT JOB '+value);
	    		}
	    	}
	    	public function cancelLastPrintJob():void
	    	{
	    		//MAKE SURE THE INSTANCE EXISTS SINCE THIS IS A PUBLICLY ACCESSIBLE FUNCTION
	    		if( getInstance() )
	    		{
		    		if( jobs.length > 1 )
					{
						jobs.pop();
					}
	    		}
	    	}
	    	private function printer_completeHandler(event:Event):void
	    	{
	    		trace('Printing complete for '+jobs.shift()+' |  Jobs remaining: '+jobs.length);
	    	
	    		if(jobs.length>0)
	    		{
	    			printer.pushJob(jobs[0]);
	    		}else{
	    			removeInstance();
	  	  		}
	    	}
	    	private function removeInstance():void
	    	{
	    		if(INSTANCE)
	    		{
	    			trace('remove instance');
		    		jobs = null;
		    		printer = null;
	    			INSTANCE = null;
	    		}
	    	}
	}
}
class SingletonEnforcer{}

We’ll also need to change our PrintScreenView a little bit since we’re using a new class. So instead of the “PrintSpoolerSingleton” class we’ll import “PrintSpoolerSingletonRemovable” in the same package. We’ll also change the “addButton_clickHandler” and the “removeButton_clickHandler” functions to reference “PrintSpoolerSingletonRemovable.getInstance()” instead of “PrintSpoolerSingleton.getInstance()”.

As you can tell from the constructor in our “PrintSpoolerSingletonRemovable” class, it’s a little bit different in it’s implementation. First of all, we are creating a class outside of the package meaning that only this specific class can access our SingletonEnforcer class. We then pass an object of that type into our singleton constructor so nobody else can instantiate an instance of this class. We also make a check within the constructor to make sure the parameter passed into the constructor is not null since you can get away with instantiating any class with parameters by passing a null reference as a parameter.
Next, we have the getInstance() function. Just like the other one this returns a single instance of our class, except here it runs a check to see if our instance has been created and if not it creates a new one, otherwise it passes back the already created instance. This is needed to keep the instance accessible later for removal if necessary. We’ll also create our new printerClass and jobs array here as well.
Our public functions have changed a little bit as well. Since there’s a possibility that our instance may not exist when these methods are called if a user created a reference to the getInstance() class rather than just referencing that method directly i.e.

var myInstance: PrintSpoolerSingletonRemovable = PrintSpoolerSingletonRemovable.getInstance();
myInstance.removeInstance();
myInstance.addPrintJob(‘some printing text’);

If we didn’t make the check, which creates an instance for us, we would get an error that there are null objects being referenced.

So we make those checks, and since this is a print spooler and when all the printing is done we no longer need to reference the class, in the complete handler I add a check to see if the spooling is done and if so, we remove the instance since it could be ages before the user prints another document, if ever. Once that is removed the garbage collector will mark it for collection and pick it up on one of it’s passes soon thereafter.

Well, there we have it. The Singleton class. It’s helpful in some instances and harmful in others. Like most patterns it really just depends on your preference of use. Now that you know the limitations and possible uses of it, I hope you’ve also learned to not take this pattern lightly and use it willy-nilly.
The singleton removes any concept of actual scope and loose coupling so just try to use it sparingly.

I’m sure some of you that read this may have an argument for or against this, so please feel free to comment and let me know how I’m correct or incorrect. And if you have any questions also don’t feel hesitant to ask. I’ll answer any questions to the best of my ability and am happy to oblige.


Posted

in

,

by

Comments

One response to “Singleton Pattern introduction”

  1. Giulian Drimba Avatar

    This is great, i aways have searching tutorials to learn the Singleton pattern, and this tutorial will help me understand how it works :D!

    Thanks!!

    Giulian Drimba.

Leave a Reply