package com.ericfeminella.utils
{
import flash.utils.Dictionary;
/**
*
* Pseudo abstract class which enforces derived classes only
* ever have a single instance instantiated per application,
* by monitoring the instantiation of derived classes
*
* <p>
* Upon instantiation of a specific derived class the super classes
* constructor is invoked, and <code>SingletonMonitor</code> parses
* the current stacktrace to determine the name of the derived class.
* The derived class name is then used as the unique key in the
* HashMap instance (<code>singletons</code>). The class name (key)
* is then assigned a Boolean value of true. When a subsequent
* instantiation of the derived class occurs the Singleton class
* constructor checks to see if the derived class has been mapped
* previously, and if so, an exception is thrown.
* </p>
*
* <p>
* Derived classes need not explicitly invoke the super classes
* constructor (<code>SingletonMonitor</code>) as it is implied
* </p>
*
* @example The following example demonstrates how a class can
* extend <code>SingletonMonitor</code> in order to simplify
* singleton implementations by abstracting the singleton
* construction process from the actual implementation code.
*
* <listing version="3.0">
*
* package
* {
* public class SomeManager extends SingletonMonitor
* {
* // Defines the singleton instance of SomeManager
* public static const instance:SomeManager = new SomeManager();
* }
* }
*
* </listing>
*
*
* @example The above example guarantees that only one instance
* of the example class "Singleton" can ever be instantiated.
*
*/
public class SingletonMonitor
{
/**
*
* Defines a static HashMap which contains a reference to all
* Singleton class types.
*
* <p>
* A unique key based on the derived class name is added to the
* map for type which is to only contain a Singleton instance
* </p>
*
*/
private static const instances:Dictionary = new Dictionary();
/**
*
* Instantiates a new <code>SingletonMonitor</code> instance
* and determines if the derived class has been previously
* instantiated, if so an Exception is thrown, thus indicating
* that the class is a Singleton and is to only ever have a
* single instance instantiated
*
*/
public function SingletonMonitor()
{
var singletonClass:String = getClassName();
if ( instances[singletonClass] )
{
throw Error("Singleton Exception. Only one instance is allowed for type: " + singletonClass);
}
instances[singletonClass] = true;
}
/**
*
* @private
*
* Determines the class name of the derived class which has
* been instantiated
*
* @return the name of the class which has been instantiated
* @see Error#getStackTrace()
*
*/
private static function getClassName() : String
{
var stackTrace:String = new Error().getStackTrace();
var stackFrame:String = stackTrace.split("at ")[3];
var className:String = stackFrame.split("()")[0];
return className;
}
}
}