Any Queries or Suggestions?

About me

Topics‎ > ‎

The Model the View and the Controller - A simple introduction with Java

Introduction



MVC 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 Model



View
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 Controller



Controllers 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 Model



There 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



6>>1:
When a model is updated by any functional part of the code, the view is notified through the registered listener in the model.

2>>3>>1:
Key event in view  notifies the controller. Controller updates the model which in updates the View

2>>4:
Key event in view  notifies the controller. Controller updates the View directly by the functionality provided by the View.

2>>5:
Key event in view  notifies the controller. Controller does required functional part in the software module.

In MVC, the Model and the Controller and not mandatory in all UI Components. Its only upon requirements these are used along with View.

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

 
  1. View implements DataChangeListener required by the model.
  2. View holds a reference to the model. It register the DataChangeListener to the model.
  3. Model may hold the multiple references of DataChangeListener, each will be notified on data change
  4. Controller implements KeyActionListener, required by the View.
  5. View holds the references of KeyActionListener, which will be notified on receiving relevent key from the user
  6. Controller may hold the reference of View or model (depending on the design), to update the View.


Pseudo code (Java)


View


 
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();

}

Comments