Cairngorm Getting Started Part Three : Singletons
Wednesday, 2. July 2008 22:07
We’ve covered an overview of the MVC pattern and how it relates to Cairngorm and we’ve set up the environment and we’ve set up the environment so we can finally start to play with some code. Nearly.
There is one last concept to go over before we move on, Singletons, I’m sure that most of you are happy with this concept, but for those who don’t here we go.
A singleton is a class that there can only be one of. Ever. To borrow a joke from someone else – like Highlander there can be only one (though this analogy doesn’t quite add up as initially there were loads of them, then they had to fight each other to whittle the numbers down to one. However the sequals made a mockerly of this idea as ‘aliens’ got involved in a typical WTF can we do now idea to make more money out of this clearly dead horse – and ruined a fantastic film. So to relate this to a design pattern is actually quite misleading.) (Don’t get me started on the Matrix sequals – he had clearly won at the end of the first one, why didn’t you stop there?)
Right, sorry I do tend to digress a bit (Star Wars prequals! WTF were they all about? On a side note when I was an actor in the London Dungeon, long story but safe to say the acting career when fantastically well
, I actually made the little boy who played Anakin Skywalker cry. So I made Darth Vader cry – sort of. Beat that!)
I did it again, concentrate – back to singletons. Like I said a singleton is a class that there can be only one of. Why is this helpful? Well if there is only one then everytime you access the class you have exactly the same data stored within t. They can be thought of as silos of data, or memory. They can also be bound to view components and this is where the concept of changing the model to change the view works. This is why they are used as a major part of the Cairngorm framework. (Lots of people don’t like singletons, and I’m still not entirely sure why)
Here is an example of a Cairngorm singleton : -
package com.worthyashes.simpleCairngorm.model
{
import com.adobe.cairngorm.model.IModelLocator;
[Bindable]
public class MemoryModelLocator implements IModelLocator
{
//Singleton code
private static var _instance:MemoryModelLocator;
public function MemoryModelLocator(enforcer:SingletonEnforcer)
{
if (enforcer == null)
{
throw new Error("Like at the end of Highlander, before the crap sequal, there can be only one");
}
}
public static function getInstance():MemoryModelLocator
{
if (_instance == null)
{
_instance = new MemoryModelLocator(new SingletonEnforcer());
}
return _instance;
}
//End of singleton code
//Pop your vars into the model from here on
}
}
class SingletonEnforcer{}
Lets go through the code
[Bindable] public class MemoryModelLocator implements IModelLocator
The [Bindable] keyword makes this class available for flex bindings so it is possible to directly bind the ModelLoactor and it’s subsequent variables to the view components as discussed above.
A Cairngorm Singleton is also known as a ModelLoactor and implements the IModelLocator interface. (For a discussion of interfaces you’re going to have to do a bit of a google. I understand them, understand how and why to use them, but for the life of me I can’t actually put into words why – I’ll have a go at a later post)
Now for the slightly mind bending bit, once you’ve got the hang of this it will all become clear.
private static var _instance:MemoryModelLocator;
This variable _instance, the underscore is there to indicate it is a private variable (the private keyword does that really, the underscore is more a visual reminder in the code), holds a reference to the MemoryModelLocator class. Which is the class that it is in. So it holds a reference to itself, in itself. Which you’d imagine would have another _instance variable, but the keyword static indicates that this variable is always the same in every single instance of this class. So every time you access the Singleton after it has initially been instantiated you are getting the same class back. I’ve just re-read that, I think it makes sense – if not then send me a mail and I’ll re-work that paragraph.
Now onto the constructor. In order for a singleton to work we need to only ever create one at any time. This means we DON’T want to be able to call the constructor directly, as this would instantiate a new class. By convention we call a static function called getInstance() (It doesn’t have to be called this, but as it’s a convention I recommend you stick to it) that returns an instance of the class.
Singletons in AS2 were easier to do. This was because it was allowed to create a class and set the constructor to be private. So you’d write something like : -
private function MemoryModelLocator()
{
}
However you can’t do this in AS3. So we have a hack. The Cairngorm team have acknowledged it as a hack, so I’ll say it too, hack, hack, hack. To understand how this hack works we need to look at the new package structure of AS3. In this case : -
package com.worthyashes.simpleCairngorm.model
{
//The class goes in here
}
Now if I put another class in this package (folder) I would be able to instantiate the MemoryModelLocator class without importing it and use the functions within it. I could create an instance of the class without any bother at all, and we want to stop this. So we create a class outside the package declaration.
//End of class
}
class SingletonEnforcer{}
This class is outside the curly brackets that close off the package, and is not available to ANY class except for the MemoryModelLocator class.
So if we pop an instance of this Singleton enforcer class into the constructor of the MemoryModelLocator class then we can force the MemoryModelLocator class to only ever be instantiated by itself through the getInstance() function.
So the constructior is : -
public function MemoryModelLocator(enforcer:SingletonEnforcer)
{
if (enforcer == null)
{
throw new Error("Like at the end of Highlander, before the crap sequal, there can be only one");
}
}
and the getInstance() function looks like this.
public static function getInstance():MemoryModelLocator
{
if (_instance == null)
{
_instance = new MemoryModelLocator(new SingletonEnforcer());
}
return _instance;
}
To go through this and explain it, remember that the _instance variable is static and therefore will be the same every time this class is accessed. What we do with the getInstance() call is to first of all check if the _instance variable exists. If not then we create it by calling the constructor with an instance of the SingletonEnforcer class. This can be accessed by the getInstance() function as it is in the MemoryModelLocator class. Then we return the _instance variable. So if we make the call to the getInstance() function in the MemoryModelLocator we will ALWAYS get the same Singleton. As it is a static function (which it has to be so we can call it and return a static variable) we use it slightly differently, like this : -
var model:MemoryModelLocator = MemoryModelLocator.getInstance();
Right – hopefully that all made sense. It’s a bit confusing, but hopefully once you see the ModelLocator in action it’ll all be made clear!
Category:Cairngorm, Flex, Frameworks, Tutorials | Comments (2) | Autor: admin