I've created a sample ActionScript project that shows how a singleton can be used. You can download it here.
Here is what the files look like.
Singleton_Example.as
package { import flash.display.Sprite; import Singleton.ExampleSingleton; import classes.ExampleClass; public class Singleton_Example extends Sprite { public function Singleton_Example() { //init the Singleton by grabbing an instance of it var singleton:ExampleSingleton = ExampleSingleton.instance; var exampleClass1:ExampleClass; //set the flag singleton.flag = ExampleSingleton.FLAG1; //show the current state of the flag trace("flag state: " + singleton.flag); //creating this class will update the flag in the singleton exampleClass1 = new ExampleClass; //the flag should be updated now trace("flag state: " + singleton.flag); //update the flag here singleton.flag = ExampleSingleton.FLAG3; //make the class display the state exampleClass1.displayFlagState(); } } }
ExampleSingleton.as
package Singleton { public class ExampleSingleton { //a set of dummy values used to explain how a Singleton is manuplated public static const FLAG1:String = "value1"; public static const FLAG2:String = "value2"; public static const FLAG3:String = "value3"; public static const FLAG4:String = "value4"; //this is the only instance of the class private static const _instance:ExampleSingleton = new ExampleSingleton(SingletonLock); //list of allowed values that can be set for the flag private var _allowedValues:Array = []; //state of the flag private var _flag:String = ""; //this will control wither the Singleton is really to be accessed private var _initialized:Boolean = false; /** * Use this to return an instance of the singleton * @return * */ public static function get instance() : ExampleSingleton { return _instance; } /** * Query the Singleton to see if it's ready to be accessed * @return * */ public function get initialized() : Boolean { return _initialized; } /** * Return the current flag * @return String * */ public function get flag() : String { return _flag; } /** * Set the flag state * @param value * @return Boolean * */ public function set flag(value:String) : void { //make sure the Singleton is initialized first if(!_initialized) { return; } //check to make sure it's an allowed value before setting it if(_allowedValues.indexOf(value) == -1) { return; } //update the flag _instance._flag = value; } /** * This will initialize the Singleton. It's never publicly called. Use ExampleSingleton.instance instead * @param lock * */ public function ExampleSingleton(lock:Class) { if(lock != SingletonLock) { throw new Error("Invalid ExampleSingleton access. Use ExampleSingleton.instance"); } initialize(); } /** * This is where you would set up anything the Singleton needed before it should be accessable to the public * */ private function initialize() : void { //we only need to initialize once. if(_initialized) { return; } //set up what we allow the flag to be _allowedValues = [FLAG1, FLAG2, FLAG3, FLAG4]; _initialized = true; } } } //this is used to lock the Singleton class SingletonLock{}
ExampleClass.as
package classes { import Singleton.ExampleSingleton; public class ExampleClass { public function ExampleClass() { //update the flag in the Singleton. we don't need to create a var to update it ExampleSingleton.instance.flag = ExampleSingleton.FLAG2; } /** * This will display the current flag from the Singleton * */ public function displayFlagState() : void { trace("flag state from ExampleClass: " + ExampleSingleton.instance.flag); } } }
Lets start with ExampleSinglton.as. The important parts of this class are the _instance member variable, the instance getter method and the ExampleSingleton constructor.
The constructor takes a SingletonLock class argument as a locking precaution. This class is defined at the bottom of the ExampleSingleton package. This allows us to control the way the class is created. The _instance member variable is where we create the instance of the ExampleSingleton. The ExampleSingleton constructor should check to make sure the lock argument is a SingletonLock class and throw an error if it isn't. The error you throw should let the person know how to properly access the singleton.
ExampleSingleton.initialize is where some basic values are set up that are accessed in the rest of the project.
Now lets look at Singleton_Example.as. When we create the singleton variable we access the .instance property of the class. This will return the single instance of ExampleSingleton.
ExampleClass.as also uses the ExampleSingleton class. You'll see how setting a property on ExampleSingleton in Singleton_Example is reflected in ExampleClass and vice versa.