Wednesday, July 15, 2015

Model-View-Controller

When applying the MVC pattern, I make the graphical components in the View class private so that there is no possibility of using them directly from the Controller. This enhances information hiding/encapsulation (i.e. knowing only the minimum about another class) and modularity.

Let's say that you have a View with an input text field, a button to add 10 to the input value and an output text field to display the result:

The Controller should not directly access the text field to get the value. Instead, the View class should have a get method which the controller should call. The same applies for output. After the model has finished calculations, Controller should get the output from Model and set it to the view using a set method without directly accessing a graphical component.
public class Controller {
    public static void start() {
        Model model = new Model();
        View view = new View();
        ActionListener add10ActionListener = (ActionEvent evt) -> {
            int input = view.getInput();
            int output = model.add10(input);
            view.setOutput(output);
        };
        view.setAdd10Action(add10ActionListener);
        view.setVisible(true);
    }
    
    public static void main(String[] args) {
        Controller.start();
    }
}
public class View extends javax.swing.JFrame {
    public int getInput() {
        return Integer.parseInt(jtfInput.getText());
    }
    
    void setOutput(int output) {
        jtfOutput.setText(String.valueOf(output));
    }

    void setAdd10Action(ActionListener add10ActionListener) {
        jbAdd10.addActionListener(add10ActionListener);
    }
...
public class Model {
    public int add10(int input) {
        return input + 10;
    }
}
I think of the Controller as the boss, i.e. the class that assigns event handlers and knows the order of steps. The Model contains algorithm implementations and the View is reponsible for graphical input/output.

When you must access the view over the network (e.g. view is on a different machine), then you obviously cannot call methods of view from controller which means taht you cannot set listeners. In that case you send all state data (e.g. mouse up/down, mouse position) as JSON from view to controller, you parse the data in controller and perform appropriate actions and send data back to view.

2 comments:

Anonymous said...

Merhaba Şamil Bey, resimlerde bir sorun var galiba, zahmet olmazsa bakabilir misiniz?

Samil Korkmaz said...

Resimler bende düzgün görünüyor.