Neil Webb recently wrote about the problems with singletons in Cairngorm, and in particular the ModelLocator. In fact, there’s been a lot of criticism of Cairngorm’s over-dependence on singletons – sometimes, when working with Cairngorm it seems that everywhere you turn there’s a singleton waiting to bite you.

Well, I started looking into Cairngorm last week for a client’s project. It’s all part of a move to Actionscript 3 at their place, and the project needs to be done ASAP (don’t they always) so using a framework rather than building our own seems like a good start point. Anyway, you may know how I dislike singletons, so Neil’s post came at a very opportune moment.

The first interesting thing about the Cairngorm’s ModelLocator is that it’s not tied into the framework in any way. The IModelLocator interface is empty, and the ModelLocator is not referenced from any code within the framework. All of which means we don’t have to use a singleton. We don’t even have to use a ModelLocator. It just so happens that the Cairngorm docs and all of the examples I’ve seen indicate that one should use a ModelLocator and it should be a singleton. But that’s just one opinion repeated by lots of people. Neil’s started looking for better alternatives and I’m all for that.

The next thing to note is, since Cairngorm doesn’t care about the ModelLocator, we can choose to split it into multiple classes, breaking our model into simpler constituent parts.

Beyond this, in looking to improve the ModelLocator I have one feature I’d like to keep – the idea of binding to data within the view. More specifically, the idea that the view could potentially be built by less experienced developers dragging components into an MXML document and binding them to the model data. This is perfect for my client’s project.

So, my first idea was to use a Monostate. By which I don’t mean a class with lots of public static variables but a true monostate, where common data is in private static variables and is accessed via public methods or getter/setters. So, a ModelLocator containing a single property would look something like this

package model
{
  [Bindable]
  public class ModelLocator
  {
    private static var _username:String;
    public function get username():String
    {
      return ModelLocator._username;
    }
    public function set username( value:String ):void
    {
      ModelLocator._username = value;
    }
  }
}

That is a lot more code than a simple public variable, but it lets us define an interface (the getters and setters) and extend the class to add more features. The idea is that we can create as many instances of the ModelLocator as we like and all will be accessing the same data.

Unfortunately, it doesn’t work. The binding fails. Probably because we’re binding to different instances of the getters and setters. Which leads me to think of another solution. One that doesn’t involve removing the singleton, just hiding it.

We start with a normal singleton class to hold the model data.

package model
{
  [Bindable]
  public class Model
  {
    private static var _instance:Model;

    public static function getInstance() : Model
    {
      if (_instance == null)
      {
        _instance = new Model();
      }
      return _instance;
    }
		
    public function Model()
    {
      if ( _instance != null )
      {
        throw new Error( "The model class is a singleton." );
      }
    }
		
    public var username:String;
  }
}

Then we add a class that is used to access this singleton, with properties bound to the singleton.

package model
{
  import mx.binding.utils.BindingUtils;

  [Bindable]
  public class ModelLocator
  {
    private var _model:Model;
		
    public var username:String;

    public function ModelLocator()
    {
      _model = Model.getInstance();
      BindingUtils.bindProperty(this,"username",_model,"username");
      BindingUtils.bindProperty(_model,"username",this,"username");
    }
  }
}

Now we can create as many instances as we like of this new ModelLocator class and bind to its properties, and all will be well. So, Actionscript code can contain, for example

var model:ModelLocator = new ModelLocator();
model.username = "fred";

and equally, mxml code could contain

<model:ModelLocator id="model" xmlns:model="model.*"/>
<mx:TextInput text="{model.username}"/>

We could also make the properties into getters and setters so we can define a proper interface.

However, we are creating a lot of code. If we were to use getter/setters in the ModelLocator class there would be even more code (and more opportunity for things to go wrong). On top of that, all the bindings result in yet more code under the hood. Is there a better way?