I'm a Java beginner currently practising MVC pattern and came up with this. Could you please check if this is a proper implementation of MVC and if there are any best practices that I have broken?
public class Appka { public static void main(String[] args) { Model model = new Model(); Controller controller = new Controller(model); View view = new View(model, controller); model.addListener(view); } } public class Model { String value; List<StateChangedListener> listeners = new ArrayList<>(); public Model() { this.value = ""; } public String getValue() { return value; } public void setValue(String value) { this.value = value; notifyListeners(); } public void addListener(StateChangedListener l) { listeners.add(l); } public void removeListener(StateChangedListener l) { listeners.remove(l); } public void notifyListeners() { listeners.forEach(l -> l.stateChanged()); } } public class View extends JFrame implements StateChangedListener { private Model model; private Controller controller; private JLabel label1; private JLabel label2; private JButton button1; private JButton button2; public View(Model model, Controller controller) { this.model = model; this.controller = controller; initComponents(); } private void initComponents() { button1 = new JButton(); button2 = new JButton(); label1 = new JLabel(); label2 = new JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); button1.setText("1"); button1.addActionListener(controller); button2.setText("2"); button2.addActionListener(controller); label1.setText("label1"); label2.setText("label2"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(button1) .addComponent(label1)) .addGap(26, 26, 26) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(label2) .addComponent(button2)) .addContainerGap(113, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(24, 24, 24) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(label1) .addComponent(label2)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(button1) .addComponent(button2)) .addContainerGap(30, Short.MAX_VALUE)) ); pack(); setVisible(true); } @Override public void stateChanged() { label1.setText(model.getValue()); label2.setText(model.getValue()); } } public class Controller implements ActionListener { private Model model; public Controller(Model model) { this.model = model; } @Override public void actionPerformed(ActionEvent e) { JButton clicked = (JButton) e.getSource(); model.setValue(clicked.getText()); } } interface StateChangedListener { public void stateChanged(); }