9 December 2008 by Ian Davis
Since there’s a rather nice discussion going on around my weekend post on RMR and MVC I thought I’d dig out the description of MVC from the Gang of Four book to remind us all what we’re actually talking about. Often people forget that the GOF book didn’t include MVC as a design pattern but as a usage scenario that they decomposed into constituent patterns, most notably Observer, Strategy and Composite.
Here’s the relevant section from the book:
The Model/View/Controller (MVC) triad of classes [first described by Krasner and Pope in 1988] is used to build user interfaces in Smalltalk-80. Looking at the design patterns inside MVC should help you see what we mean by the term “pattern.” MVC consists of three kinds of objects. The Model is the application object, the View is its screen presentation, and the Controller defines the way the user interface reacts to user input. Before MVC, user interface designs tended to lump these objects together. MVC decouples them to increase flexibility and reuse.
MVC decouples views and models by establishing a subscribe/notify protocol between them. A view must ensure that its appearance reflects the state of the model. Whenever the model’s data changes, the model notifies views that depend on it. In response, each view gets an opportunity to update itself. This approach lets you attach multiple views to a model to provide different presentations. You can also create new views for a model without rewriting it.
[…reference to diagram elided…]
Taken at face value, this example reflects a design that decouples views from models. But the design is applicable to a more general problem: decoupling objects so that changes to one can affect any number of others without requiring the changed object to know details of the others. This more general design is described by the Observer design pattern.
Another feature of MVC is that views can be nested. For example, a control panel of buttons might be implemented as a complex view containing
nested button views. The user interface for an object inspector can consist of nested views that may be reused in a debugger. MVC supports nested views with the CompositeView class, a subclass of View. CompositeView objects act just like View objects; a composite view can be used wherever a view can be used, but it also contains and manages nested views.
Again, we could think of this as a design that lets us treat a composite view just like we treat one of its components. But the design is applicable to a more general problem, which occurs whenever we want to group objects and treat the group like an individual object. This more general design is described by the Composite design pattern. It lets you create a class hierarchy in which some subclasses define primitive objects (e.g., Button) and other classes define composite objects (CompositeView) that assemble the primitives into more complex objects.
MVC also lets you change the way a view responds to user input without changing its visual presentation. You might want to change the way it responds to the keyboard, for example, or have it use a pop-up menu instead of command keys. MVC encapsulates the response mechanism in a Controller object. There is a class hierarchy of controllers, making it easy to create a new controller as a variation on an existing one.
A view uses an instance of a Controller subclass to implement a particular response strategy; to implement a different strategy, simply replace the instance with a different kind of controller. It’s even possible to change a view’s controller at run-time to let the view change the way it responds to user input. For example, a view can be disabled so that it doesn’t accept input simply by giving it a controller that ignores input events.
The View-Controller relationship is an example of the Strategy design pattern. A Strategy is an object that represents an algorithm. It’s useful when you want to replace the algorithm either statically or dynamically, when you have a lot of variants of the algorithm, or when the algorithm has complex data structures that you want to encapsulate.
MVC uses other design patterns, such as Factory Method to specify the default controller class for a view and Decorator to add scrolling to a view. But the main relationships in MVC are given by the Observer, Composite, and Strategy design patterns.
From this text the two key benefits of MVC are that it allows you to:
- “attach multiple views to a model to provide different presentations” (view/model decoupling)
- “change the way a view responds to user input without changing its visual presentation” (view/controller decoupling)
Unexpectedly (for me, anyway) it says nothing about decoupling models and controllers. Anyway, my observation is that if you need the above flexibility then MVC is your best bet. However, if you don’t need those particular decouplings then you are adopting needless complexity and you’ll be paying for it in the long run.