Ordinary User
Ordinary User

Reputation: 117

Java Swing MVC - best practice to implement Model

I'm trying to find out the optimal way to create/use the model of MVC pattern. I have a list (database) of Persons and a View which represents partial data of certain Person.

The question is: if I have a large database which contains large amout of data per person and I have a view panel which rappresents only small amout of data of one person, should I create a Model which maintans only rapresentable data for that view, or should I use Database directly as Model?

I will have different views which will represent different data of same database. Should database be a model for ALL views or I need to create small models for every view panel?

Here's a small example with 1 view panel and database directly as model for all view panels:

Main.java

import java.awt.EventQueue;
import javax.swing.JFrame;

public class Main {
    private JFrame frame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    new Main();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public Main() {
        initialize();
    }

    private void initialize() {

        Database.getInstance();                         // model ?
        View view = new View();                         // view
        Controller controller = new Controller();       // controller

        Database.getInstance().addObserver(view);
        view.addController(controller);

        frame = new JFrame();
        frame.add(view.createView());
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

Person.java

public class Person {

    private String name;
    private int age;
    private String sex;

    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getSex() {
        return sex;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

}

Database.java (model)

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

public class Database extends Observable {

    private static Database instance = null;
    private List<Person> database = new ArrayList<Person>();

    private Database() {
        this.database = createDataBase();
    }

    public static Database getInstance() {
        if (instance != null)
            return instance;
        else
            return instance = new Database();
    }

    private List<Person> createDataBase() {
        List<Person> database = new ArrayList<Person>();
        database.add(new Person("A", 25, "male"));

        return database;
    }

    public List<Person> getDatabase() {
        return database;
    }

    public void changeData(String name, int age, String sex) {
        database.get(0).setName(name);
        database.get(0).setAge(age);
        database.get(0).setSex(sex);
        setChanged();
        notifyObservers();
    }

}

View.java

import java.awt.BorderLayout;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class View implements Observer {

    private JLabel nameLabel;
    private JLabel ageLabel;
    private JButton changeDataButton;

    public View() {
        this.nameLabel = new JLabel();
        this.ageLabel = new JLabel();
        this.changeDataButton = new JButton("Change Data");
    }

    public JPanel createView() {
        JPanel viewPanel = new JPanel(new BorderLayout());
        viewPanel.add(new JLabel("View only name and age"), BorderLayout.NORTH);
        viewPanel.add(nameLabel, BorderLayout.WEST);
        viewPanel.add(ageLabel, BorderLayout.EAST);
        viewPanel.add(changeDataButton, BorderLayout.SOUTH);

        inizializeView();

        return viewPanel;
    }

    private void inizializeView() {
        this.nameLabel.setText(Database.getInstance().getDatabase().get(0).getName());
        this.ageLabel.setText("" + Database.getInstance().getDatabase().get(0).getAge());
    }

    public void addController(Controller controller) {
        changeDataButton.addActionListener(controller);
    }

    @Override
    public void update(Observable obs, Object obj) {
        nameLabel.setText(((Database) obs).getDatabase().get(0).getName());
        ageLabel.setText("" + ((Database) obs).getDatabase().get(0).getAge());
    }

}

Controller.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Controller implements ActionListener {

    public Controller() {

    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        Database.getInstance().changeData("B", 30, "female");       // change model
    }

}

As You can see, view panel represents only 2/3 fields of Person. Should I implement a separate model for this view panel which represents only String name and int age of Person or I should leave everything as it?

Upvotes: 0

Views: 1667

Answers (1)

As You can see, view panel represents only 2/3 fields of Person. Should I implement a separate model for this view panel which represents only String name and int age of Person or I should leave everything as it?

I'd suggest that you leave model as it is. That's one of the benefits of M-V-C, that one single model may be displayed in many different ways, and this can mean displaying only a portion of the model's state, as you're doing or displaying it with a completely different GUI library or platform (e.g., Android). Also and even more importantly, this way, a change to the single model is reflected in all views that share the same identical model.

Upvotes: 3

Related Questions