IntroductionMVC or Model-View-Controller is a design concept used design software module that includes User Interfaces (UI), usually Graphical User Interfaces (GUI) MVC is a very useful concept especially when you want to keep the UI part of the code separate from the functionality part. This helps in easy change of UI or even for the support for multiple UIs at the same time. This concept also helps in software development lifecycle by making UI and functionality development as parallel activities. This article gives introduction Model, View and Controller by briefing the relationship between them. View and ModelView is the part of the code that does the UI drawing. In Java, it is the class that have the inherited paint method (Eg: JComponent, JButton) or the classes that have access to the graphics object. The other methods in these classes are mainly the methods that provide instructions to the paint function on how to draw a component. Eg: setSize() that sets the size of the component and setPosition() that sets the location of the component. Model is a user specific data that influences the drawing of UI component. Usually these data are used to display some information in the component. On an MVC, a View generally has a method to set the model. The paint method, will take this model as input to draw the component appropriately. Things get bit complicated when a Model is dynamic. For a change in model, UI need to be updated or repainted. In cases where a UI component is made up of multiple child components, the entire UI component need not be repainted when a model is changed. Instead, for better performance, only the affected child component needs to be updated. In MVC, a listener /callback mechanism is used to update the View when a model is changed. This is the core of the Model-View relation in MVC and this is how it is implemented The model will have a method, say addDataChangeListener(DataChangeListener l), to register the listeners that will be notified when any change in the model happens (See Model Code given below). The view will implement this Listener Interface and registers itself to the model when the addModel() method in the View is called (See View Code given below). Model, when the data changed, notified appropriate function of all registered listeners. The view will repaint the appropriate component when listener is notified. Different function in the listener will be implemented in such a way that it repaints only the relevant sections in the View, thus optimizing the painting. You will notice one thing here. The model is unaware of View. It merely notifies the changes to all its listeners and the View here just one among them. But of course, the model is designed such a way that it causes minimum repaint in the View. View and ControllerControllers handles the user input for a View. Controllers are used mainly when a View is generic. For example in a Button, though every button looks the same, the clicks of a button have different action in different places and therefore are kept separate from the view. These user-specified action handlers are called controllers. Controllers are also implemented by listener/Callback mechanism. The view will provide mechanism to register the listeners for action (See Controller Code given below). When in focus, a view usually will have access to all the key inputs from the user. It discards all the keys other that ones required by the component. On receiving the user specified key, it calls the registered listener, thus invoking the action. In cases where a Parent View can contain multiple internal/child components, these internal components may have listeners to do actions when these components are in focus. These can be actions like moving focus from one internal component to another, or may be actions for which the user of the View doesn’t have any control. Such internal actions are all considered as the part of the View. The controllers for this Parent View are the action listeners registered to Parent View by the user. Controller and ModelThere are certain situations where the action invoked by the user in a UI component results in the updating of the UI component. In such cases, the controller updates the model and the models in turn notified the View through registered callback. There are also cases where a controller updates a View directly without going the way through model. This could be due some design strategy or due to the data in the component being too small that it doesn’t require a model. For Eg the SetText() function in JButton, where the data is changed by the method provided by the View. MVC Control Flow
For example consider a UI used just to display a static icon. Since it doesn't receive any key event on its behalf and doesn't have any data on it, there will be no Controller and model for this kind of UIs. In another example of a simple Button, since the data displayed in the Button is just its name, there will be no model for this. Instead, the View will provide methods to update the name. Button will anyway have the controller to receive all the key events. In an example of JList, the data displayed are bit huge and dynamic. JList also receive key inputs from the user. This is a perfect example of MVC, having the model, the View and the Controller. Class Diagram
Pseudo code (Java)
|
| public class SampleView extends JComponent implements DataChangeListener { private SampleModel model = null; private KeyActionListener controller = null; public void addModel(SampleModel m){ //.. m.addDataChangeListener(this); model = m; //.. } public void updateModel(SampleModel m){ //.. m.addDataChangeListener(this); model = m; //.. } /** * Does only repainting on the required subcomponents. * */ public void fullDataChanged(String anyParams) { //.. } /** * Does only repainting on the required subcomponents. * */ public void dataChanged_1(int anyParams) { //.. } /** * Does only repainting on the required subcomponents. * */ public void dataChanged_2(char anyParams) { //.. } /** * Paint by taking the data from the model. */ public void paint(Graphics g) { //.. } /** * This function is used to register the controller. * This controller will get called on receiving the required key * from the user. */ public void addActionListener(KeyActionListener c){ //.. controller = c; //.. } } |
Model
public class SampleModel { /** * Here only one listener can be registered. But in may not be the case. * All the interested parties, not only the view, is allowed to register * get any change notification. * There can also be multiple types of listeners. */ private DataChangeListener list = null; public void addDataChangeListener(DataChangeListener l){ // ...... list = l; // .... } /** When a model is updated, the corresponding listener is notified. */ public void updateData1(int anyData){ //.... list.dataChanged_1(anyData); //.... } public void updateData2(char anyData){ //.... list.dataChanged_2(anyData); //.... } public void updateAllData(String anyData){ //.... list.fullDataChanged(anyData); //.... } } |
| /** * Listener interface that is notified when a model is changed. */ public interface DataChangeListener { void dataChanged_1(int anyParams); void dataChanged_2(char anyParams); void fullDataChanged(String anyParams); } |
Controller
/** This instance of this class is registered by the user to get the * required key event from the View */ public class SampleController implements KeyActionListener { public void doAction() { //.. } } |
| /** The implementation of this Listener, controller, is registered to * the view to perform action when a required key is invoked by the user.*/ public interface KeyActionListener { void doAction(); } |

