|
A program can often be divided into two parts:
- The "Model" : the internal working "guts" of
the program where the processing actually takes place.
- The "View": the input and output of the program which
interacts with the user.
The view takes the user input and passes the information onto the
model. The model outputs information to the view, which then presents it to
the user.
In the spirit of loose coupling the following ideals should be enforced:
- The model should operate independently from the manner in which the view
interacts with the user.
- The view should be tailored to meet the interaction needs of the user, independent
of the model below it.
This has the following implications:
- The input/output interface of the model will not necessarily match as the
corresponding input/output interface (the model side, not the user side) of the
view.
- A model should work with a number of different views.
- A view should work with a number of different models.
- In general, in order for a model and view to communicate, an "adapter" object
is needed to translate the output of one into the input of the other.
- Neither the model nor the view is capable of creating the adapter that connects them
because each is unaware of the other.
Therefore, what we need is one more component, the "Controller".
The controller "knows" about both the specific model and specific
view being used. The controller's job is:
- To instantiate both the model and the view.
- To instantiate the adapter(s) used to communicate between the model and view.
- To establish the connections between the adapter and the view and between the adapter
and the model.
The Model-View-Controller ("MVC") design pattern
decouples the model from its view, enabling loose coupling and the ability to change
one without affecting the other.
To communicate from the model to the view and vice versa, the Command
Design Pattern is used. In short, a command is encapsulated as an object, very
similarly to a strategy. To invoke the command, the comand issuer executes a
specificly designated method of the command object. The issuer is unaware of
and thus decoupled from the recipient of that command. The
model-view-controller pattern, the model and view issue commands to each
other. Since the model and view are unaware of each other's interfaces,
those commands are also interface adapters.
The command adapters used between the model and the view come in several flavors:
- The "null" adapter: This is a direct
connection between the model and view. One should consider this a lucky
coincidence and the design of neither the view nor the model should be driven by attempts
to create null adapters.
- The object adapter: This type of adapter pattern uses
composition to achieve its purpose. the adapter is a subclass of
the class that one side wants to communicate with. It holds an
instance of the class the other side wants.
- The class adapter: This type of adapter uses multiple
inheritance. It inherits from the class for one side or implements its
desired interface. It also implements the interface for the other side.
This type of adapter does not promote total decoupling of the view from the model however,
so it is not recommended for those sorts of situations.
- The "dispatching" adapter: This type
of adapter is used in situations where an observer-observable pattern is desired but the
command issuer does not support it. The adapter receives a single command but then
relays that command to a number of different receievers.
For a more detailed discussion on how adapters work, see the web pages on the Adapter Design Pattern.
Multi-piece Models and Views
Often the model is not a single monolithic piece, but rather a collection of loosely
coupled sub-models. One can still use a MVC pattern without resorting to
encapsulating the submodels into a single model object by considering this:
To any given sub-model, the rest of the sub-model pieces are
simply part of its view.
Likewise, the same ideas apply if the view is broken into sub-views.
Thus, the controller can treat the sub-model pieces and the sub-views
equivalently. The controller simply is tasked to hook all the pieces together
to form a cohesive total program.
|