Search code examples
javaswingjtableobserver-pattern

Observer Design Pattern - Need help to understand why this is not working


Would someone be kind enough to look at this simple program and tell me what's wrong with the implementation of the Observer design pattern?

When I run it, nothing shows up in the table (was showing before the implementation).

I'm just starting to learn design patterns so I'm not sure how to debug it.

My teacher gave us this example of a program with Observer design pattern... and it doesn't seem to work!

The program is just data in data out in a jTable.

I thank you in advance –> here's the complete code

Here is the data entry GUI:

package com.employe.listing;

import java.util.ArrayList;

public class addEmployeJFrame extends javax.swing.JFrame {

    ArrayList<addEmployeJFrameObserver> observers = new ArrayList<>();

    public addEmployeJFrame() {
        initComponents();

    }

    public synchronized void addAddEmployeJFrameObserver(addEmployeJFrameObserver observer) {
        observers.add(observer);
    }

    public synchronized void removeAddEmployeJFrameObserver(addEmployeJFrameObserver observer) {
        observers.remove(observer);
    }

    public synchronized void notifyAddEmployeJFrameObserver(Employe e) {

        for(addEmployeJFrameObserver o : observers) {
            o.NotifyAddEmployeJFrame(e);
        }

    }                     

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         

        Employe employe = new Employe();
        employe.setName(jTextField1.getText());
        employe.setJob(jTextField2.getText());
        employe.setSalary(Integer.parseInt(jTextField3.getText()));
        employe.setYearsAtWork(Integer.parseInt(jTextField4.getText()));

        notifyAddEmployeJFrameObserver(employe);
    }                                        

    // Variables declaration - do not modify                     
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JTextField jTextField1;
    private javax.swing.JTextField jTextField2;
    private javax.swing.JTextField jTextField3;
    private javax.swing.JTextField jTextField4;
    // End of variables declaration                   
}

Here is the controller:

package com.employe.listing;

import java.util.ArrayList;

public class Controller implements addEmployeJFrameObserver {

    ArrayList<Employe> employes = new ArrayList<>();
    ArrayList<ListingEmployesJFrameObserver> observers = new ArrayList<>();
    addEmployeJFrame EmployeJFrame;
    ListingEmployesJFrame listingJFrame;

    public Controller() {

        listingJFrame = new ListingEmployesJFrame();
        EmployeJFrame = new addEmployeJFrame();
        EmployeJFrame.addAddEmployeJFrameObserver(this);
        listingJFrame.setVisible(true);
        EmployeJFrame.setVisible(true);

    }

    public synchronized void addListingEmployesJFrameObserver(ListingEmployesJFrameObserver o) {
        observers.add(o);
    }

    public synchronized void removeListingEmployesJFrameObserver(ListingEmployesJFrameObserver o) {
        observers.remove(o);
    }

    public synchronized void notifyListingEmployesJFrameObserver(ArrayList<Employe> employes) {
        for(ListingEmployesJFrameObserver o : observers) {
            o.notifyListingEmployesJFrame(employes);
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        Controller controler = new Controller();

    }

    public void addEmploye(Employe employe) {

        employes.add(employe);

        notifyListingEmployesJFrameObserver(employes);

    }

    public ArrayList<Employe> getListEmployee() {
        return employes;
    }


    @Override
    public void NotifyAddEmployeJFrame(Employe e) {
        this.addEmploye(e);
    }
}

and here's the jTable (data out):

package com.employe.listing;


import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;

public class ListingEmployesJFrame extends javax.swing.JFrame implements ListingEmployesJFrameObserver {

    ArrayList<Employe> employes = new ArrayList<>();

    /**
     * Creates new form ListingEmployesJFrame
     */
    public ListingEmployesJFrame() {
        initComponents();

        AbstractTableModel model = new AbstractTableModel() {

            @Override
            public String getColumnName(int column) {
                if(column == 0) {
                    return "Name";
                } else if(column == 1) {
                    return "Job";
                } else if(column == 2) {
                     return "Salary";
                } else {
                    return "Years";
                }
            }

            @Override
            public int getRowCount() {
                return employes.size();
            }

            @Override
            public int getColumnCount() {
                return 4;
            }

            @Override
            public Object getValueAt(int rowIndex, int columnIndex) {

                if(columnIndex == 0) {
                    return employes.get(rowIndex).getName();
                } else if(columnIndex == 1) {
                    return employes.get(rowIndex).getJob();
                } else if(columnIndex == 2) {
                     return employes.get(rowIndex).getSalary();
                } else {
                    return employes.get(rowIndex).getYearsAtWork();
                }
            }
        };

        jTable1.setModel(model);
    }


    // Variables declaration - do not modify                     
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTable jTable1;
    // End of variables declaration                   

    @Override
    public void notifyListingEmployesJFrame(ArrayList<Employe> employes) {
        this.employes = employes;
        jTable1.updateUI();
    }

}

Solution

  • I don't see anywhere in your code where you are calling addListingEmployesJFrameObserver() to register an observer, so there are none to notify.

    Update the constructor of your Controller.java as show below:

    public Controller() {
        listingJFrame = new ListingEmployesJFrame();
        EmployeJFrame = new addEmployeJFrame();
        EmployeJFrame.addAddEmployeJFrameObserver(this);
    
        listingJFrame.setVisible(true);
        EmployeJFrame.setVisible(true);
    
        // * add the line below to register listingJFrame as an observer *
        addListingEmployesJFrameObserver(listingJFrame);
    }
    

    Edit: It's worth pointing out that calling addListingEmployesJFrameObserver() isn't a recommended practice. See What's wrong with overridable method calls in constructors? for more explaination.