Tom Schober

Software – Photography – Dancing – Flight – Hockey – Music – Travel – Surf

Singleton Pattern in Cairngorm 2.1 with Actionscript 3

Posted by tomschober on January 12, 2007

So, I’m an experienced software engineer diving into the world of Rich Internet Applications (RIA) using Flex. After attending Adobe MAX 2006 in Las Vegas I was inspired to follow the Cairngorm bandwagon that even Adobe seems to have adopted as a gospel design pattern.

Call me OCD, but I analyze the daylights out of every new direction I take in programming. I don’t want to be associated with something that could possibly be dropped like a bad habit in the near future (f.y.i. In my mind so far, Cairngorm = Good). So let’s take a look at what Cairngorm is trying to accomplish, and an inherent flaw in ideology that I recently discovered.

Cairngorm is an adaptation of existing design patterns (mainly from J2EE and .NET) that are applied to the new RIA paradigm. The subject of this discussion will focus on one core pattern in particular that it has taken on as its own.

The Singleton Pattern

This veteran in the design pattern world is a tried and true way of insuring that one and ONLY one instance of an object is created and used at any given time during the life of an application. For Cairngorm this applies to some key components:

ModelLocator – Used to store the client-side model
ViewLocator – Stores/Manages view names
CairngormEventDispatcher – Used to broadcast user gesture events

These objects absolutely MUST be singletons. We can’t have two different ModelLocators running wild in our application. Traditionally we prevent this from happening with the Singleton Pattern.

An example (taken from java.sun.com)

public class MySingleton{
   private static MySingleton _instance = new MySingleton();
   private MySingleton(){
        // construct object . . .
   }
   public static MySingleton getInstance(){
        return _instance;
   }
   // Remainder of class definition . . .
}

The key component of this implementation of the Singleton is the Private Constructor. In Java for example, making the constructor private disallows any external objects from creating a new instance of our Singleton. You get a GOLD STAR if an alarm just went off in the Actionscript portion of your brain. Actionscript 3 DOES NOT ALLOW PRIVATE CONSTRUCTORS. Yikes! All is not lost. A loosely interpreted version of the Singleton Pattern is still possible as long as we adhere to the core principle of disallowing the instantiation of more than one of our would-be singletons.

But first… the faulty Cairngorm 2.1 documentation
This example of how Cairngorm suggests you implement the ModelLocator as a singleton:

[Bindable]
public class ShopModelLocator implements ModelLocator{
   private static var modelLocator :  ShopModelLocator;
   public static function getInstance() : ShopModelLocator{
        if ( modelLocator == null )
             modelLocator = new ShopModelLocator();
        return modelLocator;
   }
   public var products :  ICollectionView;
}

Right away you can see that this wasn’t written for AS3. Private constructor definitions are no longer allowed.

Here is an implementation in the Cairngorm Store (taken from IterationTwo):

[Bindable]
public class ShopModelLocator implements ModelLocator
{
   private static var modelLocator : ShopModelLocator;

   public static function getInstance() : ShopModelLocator
   {
        if ( modelLocator == null )
        {
             modelLocator = new ShopModelLocator();
        }

        return modelLocator;
    }

    //Constructor should be private but current AS3.0 does not allow it yet (?)...
    public function ShopModelLocator()
    {
         if ( modelLocator != null )
         {
              throw new Error( "Only one ShopModelLocator instance should be
              instantiated" );
         }

         shoppingCart = new ShoppingCart();
         productComparator = new Comparator();
         currencyFormatter = getInitialisedFormatter();
         assets = new CairngormStoreAssets();
    }

Here it is noted that the AS3 problem is known, and a workaround is provided. This is what set the alarm bells off in my head! A workaround… already? Is this not as stable as I thought?

Solutions
Here are a couple solutions I’ve discovered:

Creating a Public Yet Inaccessible Constructor
An excerpt from a blog post by Jeff Tapper

public function DataManager(pri:PrivateClass, wsdl:String){
}
/*
PrivateClass is used to make DataManager constructor private
*/
private class PrivateClass{
   public function PrivateClass(){
}

“Since AS3 doesn’t currently have private constructors (I’m still hoping this gets added into the language before its released), the constructor takes an instance of PrivateClass as an argument. Since PrivateClass is defined as a private class, its only available within this same file. This ensures that the constructor can not be called externally, essentially giving us a private constructor.” – Jeff Tapper

The “Have I Been Created” Flag
Inspired by a blog post by Michael at Createage.com

/*
*  Class is a Singleton
*/
public class Welcomer
{
   private static var instance:Welcomer;
   private static var create:Boolean;

/**
* Constructor – Singleton
*/
public function Welcomer()
{
   if ( !create )
   {
        throw new Error("Class cannot be instantiated");
   }
}

/**
* Returns the one single instance of this class
*/
public static function getInstance():Welcomer
{
   if (instance == null)
   {
   create = true;
   instance = new Welcomer();
   create = false;
   }

   return instance;
}

/**
* Returns a welcoming message with the provided name.
*/
public function welcome( name:String ):String
{
   return "Hello " + name;
}

In this case the constructor does a check to see if the “create” variable (stored in the singleton) is true or false. If true, then allow one to be instantiated; if false, then throw an error up to the culprit code.

Pros: This is logically easy to understand and works for AS3
Cons: Watch out if the next version of Actionscript becomes multithreaded. Checking a global variable is one of the things that raise eyebrows in determining thread-safety. AS3 is NOT multi-threaded and so, this works… for now. See this blog post that covers Multithreading and Actionscript.

Why is the Cairngorm Store not using the SINGLETON_EXCEPTION??
This is just a fun question that I pose to the Cairngorm Store folks: Why not throw the SINGLETON_EXCEPTION when you catch some rogue code trying to create another ModelLocator, etc.?

http://www.cairngormdocs.org/docs/cairngorm_2_1/com/adobe/cairngorm/CairngormMessageCodes.html

Tom Schober
Lone Palm Creative Solutions

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>