18.1 The General Architecture of MVC

 <  Day Day Up  >  

Before we study our specific clock example, let's explore the general structure of the MVC design pattern.

18.1.1 Communication in MVC

Although the model, view, and controller classes in MVC are intentionally segregated, they must communicate regularly. The model must send notifications of state changes to the view. The view must register the controller to receive user interface events and, possibly, request data from the model. The controller must update the model and, possibly, update the view in response to user input.

To facilitate this communication, each object in MVC must store a reference to the other object(s) with which it interacts . Specifically, the model instance needs a reference to the view instances that render it, while the view and controller each needs a reference to the model and reciprocal references to each other. Figure 18-1 shows how the objects in MVC reference one another. The diamond shape in the figure represents a composition relationship, in which one object stores an instance of another.

Figure 18-1. Object references in MVC
figs/as2e_1801.gif

Communication proceeds in a single direction (as shown in Figure 18-2) through the object references shown in Figure 18-1, as follows :

  1. The view receives user input and passes it to the controller.

  2. The controller receives user input from the view.

  3. The controller modifies the model in response to user input (or, in some cases, the controller modifies the view directly and does not update the model at all).

  4. The model changes based on an update from the controller.

  5. The model notifies the view of the change.

  6. The view updates the user interface, (i.e., presents the data in some way, perhaps by redrawing a visual component or by playing a sound).

Figure 18-2 depicts the MVC communication cycle. The starting point for the cycle is typically the receipt of user input. However, another part of the program could also start the cycle by modifying the model directly (perhaps in response to new data arriving from a server).

Figure 18-2. The MVC communication cycle
figs/as2e_1802.gif

Note that Figure 18-2 shows the simplest case of MVC, with a single model, a single view, and a single controller. However, it's not uncommon for an application to provide two or more views for a single model. For example, in our MVC clock implementation, we'll use one model to manage the time, but we'll have three views ”one to represent the clock in digital format, one to represent the clock in analog format, and one to display buttons that start, stop, and reset the clock. You may wonder how these buttons qualify as a view of the clock given that they do not represent the time. Views do not necessarily have to represent the entire model and need not even represent the same information (the way the analog and digital views do). As we'll see later, the buttons in our clock do not indicate the current time; instead, the button states reflect whether the clock is currently running, which is simply another aspect of the model.

While an MVC implementation may contain multiple views per model, every view has exactly one controller instance and vice versa. Each view's controller is dedicated to that view's sole service.

The view and the controller form an indivisible pair. MVC requires that each view has a controller (even if it is just the placeholder value, null ) and each controller has a view.


Some views do not allow user input. For example, a view might be a simple graph that cannot be edited. When a view accepts no user input, it does not need a controller to translate user input into model updates. Hence, views that do not allow user input have either null in place of a controller or a controller that does nothing in response to user input.

18.1.2 Class Responsibilities in MVC

As we've already learned, responsibilities in an MVC implementation are divided among the model, view, and controller. By the end of this chapter, you should be mumbling the MVC mantra to yourself at the grocery store ”"the model manages data and logic, the view creates the interface, and the controller processes user input." Those general responsibilities break down into many specific tasks , covered next .

18.1.2.1 Responsibilities of the model

The model stores data in properties and provides application-specific methods that set and retrieve that data. The data-management methods are not generic; they are customized per application and must be known to the controller and the view. For example, the model in our clock application defines methods specific to a clock, such as setTime( ) and stop( ) . Controllers in MVC are custom written to manipulate a specific model; for example, a controller in our clock application must know about the setTime( ) and stop( ) methods in order to modify the model.

The model's data can be changed externally by an outside class or internally by its own logic. For example, the time of our clock's model might be reset by the controller in response to user input, or it might be updated because, internally, it detects the passing of a second. (It might be monitoring the operating system's built-in clock or, as in our upcoming example, tracking the passing milliseconds itself.)

The model must also provide a way for views to register and unregister themselves , and it must manage a list of registered views. Whenever the model determines that its state has changed meaningfully, it must notify all registered views.

Finally, the model implements the logic of the MVC triad . For example, the model in our clock application implements a tick( ) method that runs once per second, updating the time. The model might also provide data validation services and other application-specific utilities, such as loading the current time from a server-side application.

18.1.2.2 Responsibilities of the view

The view must create the user interface and keep it up-to-date. The view listens for state changes in the model; when the model changes, the view updates the interface to reflect the change. For example, in our clock application, when the time changes, the model notifies the three registered views. In response, the analog clock view positions the hands of a traditional clock, while the digital clock view sets the numbers in its digital display. The third, "buttons" view ( ClockTools ) changes the appearance of the buttons to indicate whether the clock is running or has been stopped .

Each view must forward all input events to its controller. It should not process any inputs itself. For example, our analog clock view might allow the user to set the time by dragging the hands of the clock. When the hands are dragged, the view merely forwards the input information to the controller, and the controller decides what to do.

Depending on the specific implementation, the view might query the model for its state in order to determine what changed when an update is received. The view never changes the model but can retrieve information from it. For example, our clock's model might tell its views that the time changed, and the views, in response, might invoke getTime( ) on the model to determine the new time. Alternatively (and more commonly), the model might send the new time to the views directly in an info object at update time. You should recognize these two options as the push and pull models discussed in Chapter 16 for the Observer pattern. See that chapter for details.

You may be wondering whether the MVC design pattern as presented makes sense architecturally. It may seem odd that, if the user changes something in the view, instead of responding immediately, the view passes the input to the controller, which passes it to the model, which notifies the view of the change, and finally the view requests the details of the change from the model and renders them for the user. Wouldn't it be easier to skip all the detailed communication and just have the view update itself whenever the user makes a change? In some sense that may be easier, and in a simple application it might be appropriate. As an application becomes more complex, however, the MVC pattern offers significant benefits. For example, in the case of our clock implementation, in which there are multiple views, the architecture allows changes in one view to be detected by and reflected in all views. Therefore, you don't have to write code to make the analog clock view notify or update the digital clock view (or vice versa). Furthermore, the logic is centralized in the model, which prevents code duplication and allows us to add or remove views at runtime with minimal effort. For example, you could add a view that displays time in 24-hour (a.k.a. military) format instead of 12- hour (a.m./p.m.) format. Complex applications demand this type of flexibility, and MVC provides the structure to implement it.

18.1.2.3 Responsibilities of the controller

The controller listens for notifications from the view based on user input and translates that input into changes in the model. In some cases, the controller makes logical decisions about the input before making a corresponding change to the model. For example, our clock application has a Reset button that resets the time to midnight. When the button is clicked, the clock controller translates the input conceptually from "Reset button clicked" to the command "Set model's time to 00:00:00."

In some special cases, the controller might also instruct the view to make changes to the user interface by calling methods on the view. The changes are sent directly to the view only when they are purely cosmetic and have no effect on the model. For example, if a user interface has buttons to alphabetize a list of names in ascending and descending order, the controller may legitimately call the appropriate sort methods on the view when those buttons are clicked. Calling the sort methods is legitimate because it does not change the underlying data stored in the model (i.e., the list of names ); only the presentation of that data changes.

18.1.3 What Creates the MVC Classes?

Through all this talk of the model, view, and controller, we still haven't seen how to make instances of those classes. That's partly because there's no single, definitive way to instantiate the classes in MVC. In our clock example, we'll create a single class, Clock , which instantiates the model, its views, and their controllers. Our Clock class sets up the MVC classes as follows:

  • Create the model

  • Create views

  • Register views with the model

Notice that the controllers are missing from the preceding list because they are created by their respective views.

Hence, our Clock class forms a wrapper around the MVC triad, packaging it into a tidy, self-contained unit. However, that's definitely not the only approach possible. At least one Java implementation suggests that the controller class should create the model, and possibly the view, in its constructor!

In our example code, we'll follow the traditional (Smalltalk) implementation of MVC, in which the model and view(s) are created by some containing class, and then the model and controller are registered for each view. When the controller for a view is not specified, the view class creates a default controller for itself automatically.

 <  Day Day Up  >  


Essential ActionScript 2.0
Essential ActionScript 2.0
ISBN: 0596006527
EAN: 2147483647
Year: 2004
Pages: 177
Authors: Colin Moock

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net