Home >
There are also two models, BookieModel and AdminModel. Models are just buckets for data. Models may become more complex and expose a set of methods as an API to act on the data they hold. Figure 20 shows the two models in Bookie.
The role of a model in a Cairngorm application is to hold data that drives the view. The controllers of the application, which are commands accessed through a FrontController, do what they need to do to get data in a form ready for the model, which may include accessing a service, then change the data on the model. The view is generally "bound" to the model's data and updates automatically through Flex's excellent binding mechanism. Again, we'll see how the view works in the next iteration.
Models are generally simple beasts. Let's look at the BookieModel:
package lcds.examples.bookie.model
{
...
[Bindable]
public class BookieModel implements ModelLocator {
This model implements ModelLocator, which is simply a marker interface, meaning that it doesn't specify any methods to implement; it just marks the class as being of a certain type. Notice that the class is annotated with the [Bindable] metadata tag, just like our ActionScript DTOs. This means any public properties on the model are available for use in Flex's binding framework.
...
private static var instance:BookieModel;
//States
public static const SIGNED_OUT:String = 'SIGNED_OUT';
public static const SIGNED_IN:String = 'SIGNED_IN';
public static const BOOKS_CHOSEN:String = 'BOOKS_CHOSEN';
public var currentState:String = SIGNED_OUT;
public var books:ArrayCollection = new ArrayCollection();
public var authors:ArrayCollection = new ArrayCollection();
public var subjects:ArrayCollection = new ArrayCollection();
public var booksToReserve:ArrayCollection = new ArrayCollection();
public var user:Person;
public var loginFailedMessage:String = "";
...
Under the "States" comment are three constants which hold unique strings that we'll use to control the state of the Application view, index.mxml. At any point, currentState can be set to any one of these constants' values, and later we'll see how the application uses those constants to define states.
Next are all the public properties that will drive the view. We'll keep a list of all the books, authors, subjects, and books to reserve on the model, as well as a reference to the person logged in. The loginFailedMessage is there to be bound to the view and set with a command in case the login process fails.
That first private variable is a static instance of a BookieModel, which should tip you off that we're going to use the singleton pattern here. Models need to be singletons, so we need to make sure there's only one instance of the object in the application. This is important, because the model represents the state of the client, and that can't be done well if there isn't a definitive, single version of that state. Here are the rest of the methods necessary to implement the singleton pattern:
...
public static function getInstance():BookieModel {
if (instance == null) instance =
new BookieModel(new ModelInitializer());
return instance;
}
public function BookieModel(initializer:ModelInitializer) {
}
...
}
}
class ModelInitializer {}
First there's a static accessor method that returns the single instance, and creates it if it's not already there. Now, in Java or other languages where you can make a constructor private, you'd do that to complete the singleton pattern, to make sure that only the class could instantiate an instance of itself. ActionScript doesn't allow private constructors, so we instead use a little hack. Inside the class, at the bottom after the end of the package block, we define another class called ModelInitializer, which is visible only to the model class because it's outside the package, but in the same file. That way, we can make sure, again, that only the model class can instantiate itself.
...
public function initialize():void {
books = new ArrayCollection();
authors = new ArrayCollection();
subjects = new ArrayCollection();
booksToReserve = new ArrayCollection();
user = null;
loginFailedMessage = "";
}
public function getReservedTillDate(reservedOn:Date):Date {
var millisecondsPerWeek:int = 1000 * 60 * 60 * 24 * 7;
// reserve books for 2 weeks
var reservedTill:Date = new Date(reservedOn.getTime() + (2*millisecondsPerWeek));
return reservedTill;
}
...
Next there are a few helper methods: one to initialize the model, which means to clear out any data that it was holding, and another to calculate a date two weeks in the future to use as a "reserved until" date for when we make reservations.
Next time we're going to see how we can unit test Flex with Flex Unit. You can always find the entire series here.







Facebook Application Development
Comments
Leave a comment