Chapter 4. Singleton Pattern

<feature><title>In This Chapter</title> </feature>

The Singleton design pattern is used to limit a class to one instance and provide global access to that instance. In many cases, you need to limit a class to only one instance. Common examples include classes that manage resources that are intrinsically singular such as selection focus, navigation history, and window depth. Consider the case of a class that manages the state of the user’s cursor. Because there is only ever one cursor, you shouldn’t have more than one instance of that class. Another example is a class that loads application settings from an XML file and provides access to those settings. You wouldn’t want to waste resources by having two instances of that class or by loading the XML file more than once.

The dilemma in such cases is how to ensure that only one instance of a class exists and how to make that one instance globally accessible. The Singleton design pattern is a time-tested solution to this problem.

Essentially, three features make up a Singleton class:

  • A private static property that holds the single instance of the class.

  • A public static method that provides access to the single instance if it’s created and creates the single instance if it hasn’t been created yet.

  • A way of restricting access to instantiating the class. This is usually achieved by making the constructor private. However, ActionScript 3.0 doesn’t have private constructors. Later in this chapter, we’ll examine an alternative way of restricting instantiation in ActionScript 3.0.

Object Instantiation

To create a new instance of a class, you use the new keyword followed by the class name. This statement calls the constructor of the class and returns a new instance, as in this example:

var myObject:MyClass = new MyClass();

This approach is almost undoubtedly a concept with which you are already familiar, but if our class uses this type of instantiation, we have no way of controlling its creation. For us to control the instantiation, we’re going to use a static method called getInstance(). Because it is static, it can be invoked before an instance of the class exists. The following is an example of a class that uses this method:

public class MyClass {

   public function MyClass() {}

   public static function getInstance():MyClass {
      return new MyClass();
   }
}

Now we can create our instances of the class by using the static method, like this:

var myObject:MyClass = MyClass.getInstance();

Restricting Instantiation

As long as the instance is always accessed via the static getInstance() method, everything works according to plan. However, notice that there is nothing to prevent someone from constructing a second instance using the new keyword. In other languages this problem would be solved by making the constructor private, but private constructors aren’t supported in ActionScript 3.0.

We could just leave the constructor public and put a big comment up at the top of the class telling other developers that this class should be instantiated only once. However, one of our goals in object-oriented programming should be to create a class that cannot be broken by improper implementation. We’ll talk more about convention, as opposed to rules, later in this chapter.

So, we have a few other options at our disposal that allow us to limit instantiation. One feature of ActionScript 3.0 is that all parameters of a method are now required unless a default value is provided. This feature includes the constructor. Therefore, you can add a parameter to the constructor that is required and type it to something that is available only from inside the class.

Note

This is not an absolute restriction since someone can get around this by passing null into the constructor. However, it is the best we can do without a true private constructor.

A second new feature of ActionScript 3.0 is the ability to add multiple class definitions to one file. You can access only one of the classes from outside the ActionScript file, and that is the class—inside the package definition—with the same name as the file name. But you can put other classes outside the package in the same file, and those classes are available only to the primary class. We’ll use this feature to create a “private” class and make it our constructor parameter’s type. It’s actually easier than it sounds:

package {

   public class MyClass {

      public function MyClass(enforcer:SingletonEnforcer) {}

      public static function getInstance():MyClass {
         return new MyClass(new SingletonEnforcer());
      }

   }

}

class SingletonEnforcer {}

You can now create an instance of MyClass using the following code:

var myInstance:MyClass = MyClass.getInstance();

Note that our current implementation doesn’t yet enforce a single instance of the class. Each time we call getInstance() our class will return a new instance. In the next section we’ll look at how to ensure that there’s only ever one instance.

Single Instance and Global Access

What can we do to enforce that the class is instantiated only once? Right now, the getInstance() method can be called multiple times just like a normal public constructor; and we also need to provide global access to this one instance. By modifying the getInstance() method slightly and adding a static property to hold our single instance, we’ll knock out both of these requirements at once.

First let’s add a private static property to the class that will hold our single instance. We need to make the property static so that it is available to our getInstance() method. Now when the static getInstance() method is called it creates an instance and stores it in the private static _instance property before returning the newly created instance. Here is how our class looks now:

package {

   public class MyClass {

      private static var _instance:MyClass;

      public function MyClass(enforcer:SingletonEnforcer) {}

      public static function getInstance():MyClass {
         MyClass._instance = new MyClass(new SingletonEnforcer());
         return MyClass._instance;
      }

   }

}

class SingletonEnforcer {}

Next, we’re going to modify the getInstance() method so that it checks whether this single instance has already been created. If it has, then it returns that instance without calling the constructor again. Check out this modification:

package {

   public class MyClass {

      private static var _instance:MyClass;

      public function MyClass(enforcer:SingletonEnforcer) {}

      public static function getInstance():MyClass {
         if(MyClass._instance == null) {
            MyClass._instance = new MyClass(new SingletonEnforcer());
         }
         return MyClass._instance;
      }

   }

}

class SingletonEnforcer {}

Singleton Versus Static Members

After examining the structure of a Singleton class, you might ask the question, “Why not just make all the properties and methods of the class static? Why do we need to have an instance at all?” There are a few reasons why a Singleton is the better approach.

The first reason is inheritance. In ActionScript 3.0, you cannot inherit static properties or methods. Therefore, if all your class’s functionality is in static methods, you cannot subclass it.

The second reason to use a Singleton pattern is so that you can refactor the class to allow more than one instance. A lesser-known design pattern called the Multiton is similar to the Singleton but allows for a managed number of instances. If you write your original class as a Singleton, you can refactor it to be a Multiton easily. For example, let’s say version 1.0 of your application had a connection manager that managed a single connection to the server; but for version 2.0, it has been determined that you need to manage a pool of 10 connections to the server. This is where a Multiton could be used.

The third reason is that it can be a waste of resources to have all this logic initialized right away. Singletons use the concept of “lazy” instantiation, because the object is created only when the first call to getInstance() is made. Classes that use all static members do what is called “eager” instantiation. This is usually a waste of resources and can slow down the startup of your application.

Lastly, objects are just easier to manage. By using static methods instead of a single object your code is not created at a specific point in your application. This can cause some strange initialization issues that are difficult to debug. This is especially true if your Singleton class has a dependency on other objects in the application that might not be initialized. For this reason, consider using static members only if your class is 100% self-contained, with no dependencies on outside objects. Even then, your class is locked into this “self-contained” mode and isn’t scalable anymore.

Building a Simple Singleton

Often a good example will go a long way when learning a design pattern. In the next few sections we’ll look at an example using the Singleton pattern.’’ In the first example, we simply create a generic Singleton and invoke it.

Creating the Singleton

We first need to create the Singleton class. Create it in the com.peachpit.aas3wdp.singletonexample package and name it Singleton. Notice that this class has all the standard elements of an ActionScript 3.0 Singleton class:

  • A private static property, _instance, to hold the single instance of the class.

  • A constructor with a parameter typed to a class, SingletonEnforcer, that is available only to the Singleton class. The SingletonEnforcer class definition is also required.

  • A public static method, getInstance(), that provides access to the single instance and creates it if it does not exist.

The following code shows an example of standard singleton class. We’ll us this to demonstrate how to build a singleton class.

package com.peachpit.aas3wdp.singletonexample {

   public class Singleton {

      static private var _instance:Singleton;

      public function Singleton(singletonEnforcer:SingletonEnforcer) {}

      public static function getInstance():Singleton {
         if(Singleton._instance == null) {
            Singleton._instance = new Singleton(new SingletonEnforcer());
         }
         return Singleton._instance;
      }

      public function doSomething():void {
         trace("SOMETHING!");
      }
   }

}

class SingletonEnforcer {}

As you can see, the doSomething() method is a public method that simply traces the text “SOMETHING!” to the console. While this example is very simple, it demonstrates the required elements of a class that follows the Singleton design pattern in ActionScript. The code in the next section demonstrates how to invoke a Singleton class.

Note

In order for trace statements to output information to the console you must debug the application rather than just run it.

Invoking the Singleton

Inside the main class, we’re going to get the instance of the Singleton class and call a method on that object. We start by importing the Singleton class. Then inside the constructor, we call the Singleton’s static getInstance() method and immediately call the doSomething() method on the returned instance. The doSomething() method simply traces “SOMETHING!” to the console.

package {

   import com.peachpit.aas3wdp.singletonexample.Singleton;
   import flash.display.Sprite;

   public class SimpleSingletonExample extends Sprite {

      public function SingletonExample() {
         Singleton.getInstance().doSomething();
      }
   }

}

Building a Settings Framework

In this next example we’ll build a simple application that uses a Singleton class called Settings to hold global values.

The Settings class loads data from an XML file at runtime and provides access to its values. It’s a simple concept, but it’s very useful to be able to change these settings without recompiling the application.

Creating the XML Document

The XML document for this framework is simple. We have a settings root node that contains multiple property nodes. Each property node has an id and a value attribute. The Settings class does a lookup on the id attribute and returns the value attribute. The following is the XML document, titled config.xml, which we’ll use in this example:

<?xml version="1.0" encoding="UTF-8"?>
<cs:settings xmlns:cs="http://www.dannypatterson.com/2006/ConfigSettings">
   <cs:property id="testOne" value="This is the first test value." />
   <cs:property id="testTwo" value="This is the second test value." />
</cs:settings>

Note that we added a namespace to this document to demonstrate how simple namespaces are to use inside E4X. For more information on XML namespaces, see Chapter 15, “E4X (XML).”

Creating the Settings Class

Now you’ll need to create a new ActionScript class named Settings and put it in the com.peachpit.aas3wdp.singletonexample package. It has three main responsibilities:

  • It follows the Singleton design pattern; therefore, it manages its creation and access the same way as the previous example.

  • The Settings class also provides access to the values in the XML file through simple property access, like this:

    var myString:String = Settings.getInstance().testOne;
  • Because testOne isn’t a property of the Settings class, we have to allow the request to come in and capture it. To enable this functionality we need to make the class dynamic so that other classes can call undefined properties. To capture these undefined requests, we’ll subclass the built-in flash.utils.Proxy class and override the getProperty() method.

  • Because this class loads an external XML file, it must have a method for loading that file and an event that is dispatched when the file has loaded successfully. To enable the class to dispatch events, we will use the built-in EventDispatcher class.

Invoking the Settings Class

Next, we’ll need a main class for the application in order to utilize the Settings class. We’ll call the main class SettingsExample, and define it as follows:

package {

   import com.peachpit.aas3wdp.singletonexample.Settings;
   import flash.events.Event;
   import flash.display.Sprite;

   public class SettingsExample extends Sprite {

      public function SettingsExample() {
         Settings.getInstance().loadSettings("config.xml");
         Settings.getInstance().addEventListener(Settings.INIT, onSettingsInit);
      }

      private function onSettingsInit(event:Event):void {
         trace(Settings.getInstance().testOne);
         trace(Settings.getInstance().testTwo);
      }

   }

}

This class is the start of the project. It retrieves the singleton instance of Settings, then it displays the values from the dynamic properties. In the constructor, we first get a reference to the single instance using the static getInstance() method. Then we call the loadSettings() method and add the Settings.INIT event listener.

Inside the onSettingsInit() event handler, we trace the value of testOne and testTwo from the Settings instance. These variables are not actually properties of the Settings class. You’ll see later in this example that the Settings class uses a new feature of ActionScript 3.0 called Proxy to handle this request and return the value from the XML document.

Now you can debug the project. You should see the values of properties testOne and testTwo being displayed in the trace console.

Summary

The Singleton design pattern is a simple yet effective solution for restricting a class to one instance and providing a global access point to it. In this chapter, you learned how to implement this design pattern using ActionScript 3.0. You also learned the importance of the Singleton pattern over simply using static members.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.147.20