Basic Concepts
3. Controller – A controller provides the interface between the model and an initiator (typically a user in a GUI application) of changes in its model(s) It depends on commands provided by the model that allow the model's internal
data to be modified. The components (or widgets) along with their event handlers in a GUI application serve as controllers. They present a graphical image for interaction with the user. Actions by the user cause the components to fire events. These events are handled in a way to effect the intended change in the model(s). The event handling part of the controller is typically consistent with a larger and more general concept for event handling. The controller needs a reference to its model(s).
The separation of roles and responsibilities for model, view, and controller is a design pattern that enables the easy addition of views or controllers without adversely affecting those already present. It provides a consistent approach to the storage, modification, and display of data. With the evolution of GUI applications, the user interface has become the software component with responsibility for both view and controller. We often speak of an M -VC design as opposed to an MVC design. Clearly, the graphical components in a GUI represent the controls for modifying data in the model as well as views for displaying the model. Figure 5.9 shows the key players in an M-VC design that uses a graphical user interface.
The interactions in Figure 5.9 represent the M-VC concept. The user initiates an action by using the keyboard or mouse to activate some visual control (component) in the GUI. The component (controller) responds by firing an event. The
eventHandler part of the controller is assumed to have registered as a listener for that kind of event and is notified of the event firing. It responds by sending a command, setData(newValue), to the model. The model responds by changing its data. It then invokes the helper object, changeMonitor, by sending it the message changed(). The helper object then notifies all registered views of the change in the model by sending them the message update(model). Using the knowledge of
Figure 5.9.
which model changed, each view then may query, for example, using getData(), the model for information required to update itself.
5.3.1—
Inheritance Approach to M -VC
The inheritance approach to M-VC requires that all model classes extend a common parent class. The parent class provides all fields and methods for maintaining a list of registered views and for notifying those views of changes in the model. This approach is great from the standpoint of good object-oriented design and maximum reusability. In Java, the common parent class for models is class java.util.Observable. Views must register as observers with the model and implement the java.util.Observer interface, which defines only one command, update. See Figure 5.10. Observable uses a Vector to store registered observers for the model.
5.3.2—
Delegation Approach to M-VC
Primary classes and their relationships are shown in Figure 5.11 for the delegation approach to M-VC in Java.
Figure 5.10.
Figure 5.11.
Delegation approach to M -VC in Java.
It is not always convenient or even possible for a model class to extend the parent class java.util.Observable; then we must use the delegation approach. The delegation approach to M-VC adds a new field to the model class. This field is the delegate object responsible for registering views with the model and for notifying registered views when the model has changed. This approach frees the model to extend any appropriate class (instead of Observable). The delegation approach to M -VC in Java is an extension of the property change mechanism in Java beans (see example in Chapter 6). Changing a property of a Java bean causes a PropertyChangeEvent to be fired. All objects that wish to be notified of the property change must register (add themselves as listeners) with the bean and implement the PropertyChangeListener
interface.
TEAM
FLY
A model class may tap into this bean behavior by adding a delegate field that is an instance of class
java.beans.PropertyChangeSupport (see Figure 5.10). Class PropertyChangeSupport provides methods for maintaining a list (using a Vector) of interested listeners to be notified of a PropertyChangeEvent. The implementations for adding and removing property change listeners in the model simply pass responsibility along to the propertyChange field. In a sense, our model is now behaving as a nonvisual Java bean. We present a simple example using this approach in Chapter 6.
The delegate also provides a command that fires the PropertyChangeEvent. At least one command in the model class (e.g., setChangeableProperty in MyModel) must invoke the expression propertyChange.firePropertyChange() to fire the event.
5.4— Summary
Graphical user interfaces are event-driven applications. The Java platform provides a rich set of classes representing the essential elements of an event-driven, GUI application. If an application interacts with data then the software developer may take advantage of the MVC design pattern to provide a more object-oriented and elegant design for the application. Java provides classes supporting two approaches to MVC: (1) the inheritance approach and (2) the delegation approach. • Top-level windows (instances of Frame or JFrame) and other container classes organize and present graphical controls to the user for interaction with a GUI application.
• Components or widgets are the graphical controls that allow a user to interact with a GUI application. Interaction with a component causes an event to be fired. Event handling by the application causes desired changes to take effect. • MVC is a design concept that separates responsibilities for (1) maintaining data used by an application (model), (2) allowing the user to modify data (controller), and (3) presenting data to the user (view).