{"id":293,"date":"2009-11-11T09:32:23","date_gmt":"2009-11-11T14:32:23","guid":{"rendered":"http:\/\/thaylin.info\/blog\/?p=293"},"modified":"2009-11-11T09:34:13","modified_gmt":"2009-11-11T14:34:13","slug":"singleton-pattern-introduction","status":"publish","type":"post","link":"https:\/\/www.thaylin.com\/blog\/2009\/11\/11\/singleton-pattern-introduction\/","title":{"rendered":"Singleton Pattern introduction"},"content":{"rendered":"<p><em>Staying on the course of my tutorial kick I&#8217;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.<\/em><\/p>\n<p>Another pattern, or rather anti-pattern according to some, is called the Singleton Pattern.<\/p>\n<p>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<!--more-->, 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. <\/p>\n<p>Sometimes you might also want to use this for storing global settings or some sort of data. Though it&#8217;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.<\/p>\n<p>There are a couple different ways in which you can implement the Singleton Pattern depending on how you may want to utilize it. We&#8217;ll look at the first example as, let&#8217;s say, a print spooler. <\/p>\n<p>We&#8217;ll place this in the &#8220;info\/thaylin\/singleton&#8221; package and call it &#8220;PrintSpoolerSingleton&#8221;.<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">\r\npackage info.thaylin.singleton\r\n{\r\n\timport flash.events.Event;\r\n\t\r\n\tpublic class PrintSpoolerSingleton\r\n\t{\r\n\t\tprivate static const INSTANCE:PrintSpoolerSingleton = new PrintSpoolerSingleton();\r\n\t    private var printer:PrinterClass = new PrinterClass();\r\n\t    private var jobs:Array = new Array();\r\n\t    \r\n\t    public function PrintSpoolerSingleton():void\r\n\t    {\r\n\t        if (INSTANCE != null)\r\n\t        {\r\n\t            \/\/Flash forces constructors to be public\r\n\t            \/\/An error is thrown to prevent any new instances from being created.\r\n\t            throw new Error(\"An instance of Singleton already exists.\");\r\n\t        }\r\n\t        \r\n\t    }\r\n\t    public static function getInstance():PrintSpoolerSingleton\r\n\t    {\r\n\t        return INSTANCE;\r\n\t    }\r\n\t    public function addPrintJob(value:String):void\r\n\t    {\r\n        \tif(!printer.hasEventListener(PrinterClass.PRINTJOB_COMPLETE))\r\n        \t{\r\n        \t\tprinter.addEventListener(PrinterClass.PRINTJOB_COMPLETE, printer_completeHandler);\r\n        \t}\r\n    \t    jobs.push(value);\r\n    \t    if(jobs.length == 1)\r\n    \t    {\r\n\t    \t    printer.pushJob(value);\t\r\n    \t    }\r\n    \t    trace('ADDING PRINT JOB '+value)\r\n\t    }\r\n\t    public function cancelLastPrintJob():void\r\n\t    {\r\n\t    \tif( jobs.length > 1 )\r\n\t    \t{\r\n\t    \t\tjobs.pop();\r\n\t    \t}\r\n\t    }\r\n\t    private function printer_completeHandler(event:Event):void\r\n\t    {\r\n\t    \ttrace('Printing complete for '+jobs.shift()+' |  Jobs remaining: '+jobs.length);\r\n\t    \t\r\n\t    \t\r\n\t    \tif(jobs.length>0)\r\n\t    \t{\r\n\t    \t\tprinter.pushJob(jobs[0]);\r\n\t    \t}\r\n\t    }\r\n\t    \r\n\t}\r\n}\r\n<\/pre>\n<p>And in case you would like to follow along here is that &#8220;PrinterClass&#8221; class within the &#8220;info\/thaylin\/singleton&#8221; folder as well.<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">\r\npackage info.thaylin.singleton\r\n{\r\n\timport flash.events.Event;\r\n\timport flash.events.EventDispatcher;\r\n\timport flash.events.IEventDispatcher;\r\n\timport flash.events.TimerEvent;\r\n\timport flash.utils.Timer;\r\n\r\n\tpublic class PrinterClass extends EventDispatcher\r\n\t{\r\n\t\tprivate var timer:Timer = new Timer(3000, 1);\r\n\t\tpublic static const PRINTJOB_COMPLETE:String = 'printJobComplete';\r\n\t\tpublic static const PRINTJOB_STARTED:String = 'printJobStarted';\r\n\t\tpublic function PrinterClass(target:IEventDispatcher=null)\r\n\t\t{\r\n\t\t\tsuper(target);\r\n\t\t\ttimer.addEventListener(TimerEvent.TIMER_COMPLETE, timer_completeHandler);\r\n\t\t}\r\n\t\tprivate function timer_completeHandler(event:TimerEvent):void\r\n\t\t{\r\n\t\t\t\/\/IMAGINARY PRINTER HAS COMPLETED IT'S PRINTING JOB\r\n\t\t\tdispatchEvent(new Event(PRINTJOB_COMPLETE));\r\n\t\t}\r\n\t\tpublic function pushJob(value:Object):void\r\n\t\t{\r\n\t\t\t\/\/PUSH A PRINT JOB TO OUR IMAGINARY PRINTER\r\n\t\t\tdispatchEvent(new Event(PRINTJOB_STARTED));\r\n\t\t\ttimer.reset();\r\n\t\t\ttimer.start();\r\n\t\t}\r\n\t\t\r\n\t}\r\n}\r\n<\/pre>\n<p>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.<\/p>\n<p>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&#8217;re forced to emulate it.<\/p>\n<p>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. <\/p>\n<p>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.<\/p>\n<p>Now let&#8217;s test our work. First we&#8217;ll create a view class in which we&#8217;ll add a couple of buttons that will add and remove jobs from the printer queue. We&#8217;ll place this in the package &#8220;info\/thaylin\/views\/&#8221; and call it &#8220;PrintScreenView&#8221;<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">\r\npackage info.thaylin.views\r\n{\r\n\timport flash.display.Sprite;\r\n\timport flash.events.MouseEvent;\r\n\t\r\n\timport info.thaylin.singleton.PrintSpoolerSingleton;\r\n\r\n\tpublic class PrintScreenView extends Sprite\r\n\t{\r\n\t\tprivate var num:Number = 0;\r\n\t\tpublic function PrintScreenView(name:String)\r\n\t\t{\r\n\t\t\tsuper();\r\n\t\t\tthis.name = name;\r\n\t\t\tinit();\r\n\t\t}\r\n\t\tpublic function init():void\r\n\t\t{\r\n\t\t\tvar addButton:Sprite = createButton(80, 40);\r\n\t\t\taddButton.addEventListener(MouseEvent.CLICK, addButton_clickHandler);\r\n\t\t\t\r\n\t\t\tvar removeButton:Sprite = createButton(80, 40);\r\n\t\t\tremoveButton.addEventListener(MouseEvent.CLICK, removeButton_clickHandler);\r\n\t\t\taddButton.x = 100;\r\n\t\t\tremoveButton.x = 200;\r\n\t\t\t\r\n\t\t\taddChild(addButton);\r\n\t\t\taddChild(removeButton);\r\n\t\t}\r\n\t\tprivate function createButton(width:Number ,height:Number):Sprite\r\n\t\t{\r\n\t\t\tvar shape:Sprite = new Sprite();\r\n\t\t\tshape.graphics.beginFill(0xFFCC00);\r\n\t\t\tshape.graphics.drawRect(0,0,width, height);\r\n\t\t\tshape.graphics.endFill();\r\n\t\t\tshape.buttonMode = true;\r\n\t\t\treturn shape;\r\n\t\t}\r\n\t\tprivate function addButton_clickHandler(event:MouseEvent):void\r\n\t\t{\r\n\t\t\tvar job:String = ('Job # '+(++num)+' ['+name+']');\r\n\t\t\tPrintSpoolerSingleton.getInstance().addPrintJob(job);\r\n\t\t}\r\n\t\tprivate function removeButton_clickHandler(event:MouseEvent):void\r\n\t\t{\r\n\t\t\tPrintSpoolerSingleton.getInstance().cancelLastPrintJob();\r\n\t\t}\r\n\t\t\r\n\t}\r\n}\r\n<\/pre>\n<p>Now that we have this in a &#8220;view&#8221; 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&#8217;ll just create 2 of these view instances.<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">\r\npackage {\r\n\timport flash.display.Sprite;\r\n\timport flash.events.MouseEvent;\r\n\t\r\n\timport info.thaylin.singleton.PrintSpoolerSingleton;\r\n\timport info.thaylin.views.PrinterView;\r\n\r\n\tpublic class Main extends Sprite\r\n\t{\r\n\t\t\r\n\t\tpublic function Main()\r\n\t\t{\r\n\t\t\tvar view1:PrinterView = new PrinterView('view1');\r\n\t\t\tvar view2:PrinterView = new PrinterView('view2');\r\n\t\t\t\r\n\t\t\tview2.y = 50;\r\n\t\t\taddChild(view1);\r\n\t\t\taddChild(view2);\r\n\t\t}\r\n\t\t\r\n\t}\r\n}\r\n\r\n<\/pre>\n<p>Now if you&#8217;ve been following along in your own project you can go ahead and test this. It&#8217;s not much for eye candy, but it&#8217;s just fine for demonstrating the Singleton. You&#8217;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&#8217;ll see our jobs being added, completed and removed. But, to really see the Singelton in action you&#8217;ll need to run the profiler if you&#8217;re using Flex Builder.<\/p>\n<p>Right click on your main class and select &#8220;Profile As > Flex Application&#8221;. A window should come up prompting you for various things relating to the profiler. The default settings should be fine, just click resume.<br \/>\nIn the Flex Profiling view you&#8217;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&#8217;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.<br \/>\nOne 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. <\/p>\n<p>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&#8217;s see if we can remove the instance.<\/p>\n<p>We&#8217;ll have to make some changes to our class so let&#8217;s go ahead and create a new class that&#8217;s similar to our old one. We&#8217;ll call it &#8220;PrintSpoolerSingletonRemovable&#8221; for lack of imagination on my part at the moment.<\/p>\n<p>Here&#8217;s the code for our new Singleton class.<\/p>\n<pre lang=\"actionscript\" line=\"1\" colla=\"+\">\r\npackage info.thaylin.singleton\r\n{\r\n\timport flash.events.Event;\r\n\t\r\n\tpublic class PrintSpoolerSingletonRemovable\r\n\t{\r\n\t\tprivate static var INSTANCE:PrintSpoolerSingletonRemovable;\r\n\t    \tprivate static var printer:PrinterClass;\r\n\t    \tprivate static var jobs:Array;\r\n\t    \r\n\t    \tpublic function PrintSpoolerSingletonRemovable(enf:SingletonEnforcer):void\r\n\t    \t{\r\n\t\t        if (enf == null)\r\n\t\t        {\r\n\t\t            \/\/Flash forces constructors to be public\r\n\t\t            \/\/An error is thrown to prevent any new instances from being created.\r\n\t\t            throw new Error(\"An instance of Singleton already exists.\");\r\n\t\t        }\r\n\t        \r\n\t    \t}\r\n\t    \tpublic static function getInstance():PrintSpoolerSingletonRemovable\r\n\t    \t{\r\n\t    \t\tif(!INSTANCE)\r\n\t    \t\t{\r\n\t    \t\t\tINSTANCE = new PrintSpoolerSingletonRemovable( new SingletonEnforcer() );\r\n\t   \t\t\t\tprinter = new PrinterClass();\r\n\t    \t\t\tjobs = new Array();\r\n\t    \t\t}\r\n\t    \t\r\n\t        \treturn INSTANCE;\r\n\t    \t}\r\n\t    \tpublic function addPrintJob(value:String):void\r\n\t    \t{\r\n\t    \t\t\/\/MAKE SURE THE INSTANCE EXISTS SINCE THIS IS A PUBLICLY ACCESSIBLE FUNCTION\r\n\t    \t\tif( getInstance() )\r\n\t    \t\t{\r\n\t        \t\tif(!printer.hasEventListener(PrinterClass.PRINTJOB_COMPLETE))\r\n\t        \t\t{\r\n\t        \t\t\tprinter.addEventListener(PrinterClass.PRINTJOB_COMPLETE, printer_completeHandler);\r\n\t        \t\t}\r\n    \t    \t\tjobs.push(value);\r\n    \t    \t\tif(jobs.length == 1)\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tprinter.pushJob(value);\r\n\t\t\t\t\t}\r\n    \t\t    \ttrace('ADDING PRINT JOB '+value);\r\n\t    \t\t}\r\n\t    \t}\r\n\t    \tpublic function cancelLastPrintJob():void\r\n\t    \t{\r\n\t    \t\t\/\/MAKE SURE THE INSTANCE EXISTS SINCE THIS IS A PUBLICLY ACCESSIBLE FUNCTION\r\n\t    \t\tif( getInstance() )\r\n\t    \t\t{\r\n\t\t    \t\tif( jobs.length > 1 )\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tjobs.pop();\r\n\t\t\t\t\t}\r\n\t    \t\t}\r\n\t    \t}\r\n\t    \tprivate function printer_completeHandler(event:Event):void\r\n\t    \t{\r\n\t    \t\ttrace('Printing complete for '+jobs.shift()+' |  Jobs remaining: '+jobs.length);\r\n\t    \t\r\n\t    \t\tif(jobs.length>0)\r\n\t    \t\t{\r\n\t    \t\t\tprinter.pushJob(jobs[0]);\r\n\t    \t\t}else{\r\n\t    \t\t\tremoveInstance();\r\n\t  \t  \t\t}\r\n\t    \t}\r\n\t    \tprivate function removeInstance():void\r\n\t    \t{\r\n\t    \t\tif(INSTANCE)\r\n\t    \t\t{\r\n\t    \t\t\ttrace('remove instance');\r\n\t\t    \t\tjobs = null;\r\n\t\t    \t\tprinter = null;\r\n\t    \t\t\tINSTANCE = null;\r\n\t    \t\t}\r\n\t    \t}\r\n\t}\r\n}\r\nclass SingletonEnforcer{}\r\n<\/pre>\n<p>We&#8217;ll also need to change our PrintScreenView a little bit since we&#8217;re using a new class. So instead of the &#8220;PrintSpoolerSingleton&#8221; class we&#8217;ll import &#8220;PrintSpoolerSingletonRemovable&#8221; in the same package. We&#8217;ll also change the &#8220;addButton_clickHandler&#8221; and the &#8220;removeButton_clickHandler&#8221; functions to reference &#8220;PrintSpoolerSingletonRemovable.getInstance()&#8221; instead of &#8220;PrintSpoolerSingleton.getInstance()&#8221;.<\/p>\n<p>As you can tell from the constructor in our &#8220;PrintSpoolerSingletonRemovable&#8221; class, it&#8217;s a little bit different in it&#8217;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.<br \/>\nNext, 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&#8217;ll also create our new printerClass and jobs array here as well.<br \/>\nOur public functions have changed a little bit as well. Since there&#8217;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.<\/p>\n<p>var myInstance: PrintSpoolerSingletonRemovable = PrintSpoolerSingletonRemovable.getInstance();<br \/>\nmyInstance.removeInstance();<br \/>\nmyInstance.addPrintJob(&#8216;some printing text&#8217;);<\/p>\n<p>If we didn&#8217;t make the check, which creates an instance for us, we would get an error that there are null objects being referenced.<\/p>\n<p>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&#8217;s passes soon thereafter.<\/p>\n<p>Well, there we have it. The Singleton class. It&#8217;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&#8217;ve also learned to not take this pattern lightly and use it willy-nilly.<br \/>\nThe singleton removes any concept of actual scope and loose coupling so just try to use it sparingly.<\/p>\n<p>I&#8217;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&#8217;m correct or incorrect. And if you have any questions also don&#8217;t feel hesitant to ask. I&#8217;ll answer any questions to the best of my ability and am happy to oblige. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Staying on the course of my tutorial kick I&#8217;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, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11,25],"tags":[32,16,31,26,24],"_links":{"self":[{"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/posts\/293"}],"collection":[{"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/comments?post=293"}],"version-history":[{"count":7,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/posts\/293\/revisions"}],"predecessor-version":[{"id":301,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/posts\/293\/revisions\/301"}],"wp:attachment":[{"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/media?parent=293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/categories?post=293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.thaylin.com\/blog\/wp-json\/wp\/v2\/tags?post=293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}