Tuesday, February 18, 2014

Prototype Design Pattern

The prototype pattern is used to get a new object by cloning an existing object instead of creating a new object when creating a new object is too costly.

For example, your JTable has a TableModel that holds data which are very expensive to query from the database, to create or to get from a remote site. You would like to provide an undo function after the user finishes modifying the data, therefore you need another instance of the TableModel to hold the data before the user makes the change to the TableModel used by the JTable. You can apply the prototype pattern here to make a copy of you JTable's model instead of querying the database for all the data, recreating the data, or retrieving from the remote.

import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

//The prototype object
class MyTableModel extends DefaultTableModel {

    public MyTableModel() {
        super();
        setColumnIdentifiers(new String[]{"Name", "Value"});
    }

    //deep clone all the data to immutable, so that modification will not over write the clone
    public MyTableModel cloneModel() {
        System.out.println("Cloning...");
        MyTableModel model = new MyTableModel();

        //deep copy to the level of immutable data
        Vector data = this.getDataVector();
        Vector rowData = new Vector();
        int size = data.size();
        for (int i = 0; i < size; i++) {
            Vector originData = (Vector) data.get(i);
            for (int j = 0; j < originData.size(); j++) {
                rowData.add(originData.get(j));
            }
            model.addRow(rowData);
            rowData = new Vector();
        }

        return model;
    }
}

//The application uses the table model
class FruitInfo extends JFrame {
    private MyTableModel model;
    private MyTableModel modelClone;
    private JTable table;
   
        public FruitInfo() {
            model = new MyTableModel();
            model.addRow(new Object[]{"Apple", new Float(1.19)});
            model.addRow(new Object[]{"Banana", new Float(0.59)});

            //make a clone of the table model
            modelClone = model.cloneModel();
           
            table = new JTable();
            table.setModel(model);
           
            JScrollPane sp = new JScrollPane(table);
            add(sp);
           
            JButton save = new JButton("Save");
            save.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    if (table.getCellEditor() != null) {
                        table.getCellEditor().stopCellEditing();
                    }
                    JOptionPane.showMessageDialog(FruitInfo.this, "Data Saved!");
                }
            });
           
            JButton undo = new JButton("Undo");
            undo.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(java.awt.event.ActionEvent e) {
                    if (table.getCellEditor() != null) {
                        table.getCellEditor().stopCellEditing();
                    }
                    System.out.println("Undo pressed!");
                   
                    //clear the table model to make it ready for importing data from modelClone
                    while (model.getRowCount() > 0){
                        model.removeRow(0);
                    }
                    Vector data = modelClone.getDataVector();
                    Vector rowData = new Vector();
                    for (int j=0; j<data.size(); j++){
                        Vector row = (Vector)data.get(j);
                        for (int r = 0; r<row.size(); r++){
                            rowData.add(row.get(r));
                        }
                        model.addRow(rowData);
                        rowData = new Vector();
                    }
                    model.fireTableDataChanged();
                }
               
            });
           
            JPanel buttonPanel = new JPanel();
            buttonPanel.add(save);
            buttonPanel.add(undo);
            add(buttonPanel, BorderLayout.SOUTH);
           
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setSize(200, 200);
            setVisible(true);
        }
    }

//The test class
public class PrototypeTest {
   
    public static void main(String[] args){
        javax.swing.SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                new FruitInfo();
            }
        });
    }
}
   
--------------------------------------------------------------------------------------------------------------       

                        
If you have ever asked yourself these questions, this is the book for you. What is the meaning of life? Why do people suffer? What is in control of my life? Why is life the way it is? How can I stop suffering and be happy? How can I have a successful life? How can I have a life I like to have? How can I be the person I like to be? How can I be wiser and smarter? How can I have good and harmonious relations with others? Why do people meditate to achieve enlightenment? What is the true meaning of spiritual practice? Why all beings are one? Read the book free here.

No comments:

Post a Comment