Previous - Big Blob, Next - MVC
The single most important structure in a program is to separate the user interface from the model (business logic, domain, ...). This provides a huge improvement in simplicity, altho at first it may not appear so. Program enhancements and maintenance are much simpler with this structure.
A further separation can be found in the next example which separates the View (displaying information) from the Controller (processing user interactions) -- the MVC pattern. However, for most applications, you will probably get most of the benefit without some of the complications by simply sticking to the Presentation-Model organization that is shown here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// structure/presentation-model/CalcV3.java // Calculator with separation of presentation and model. // Fred Swartz -- December 2004 // Program Organization: Separate View+Controller and Model import javax.swing.*; public class CalcV3 { public static void main(String[] args) { JFrame presentation = new CalcViewController(); presentation.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); presentation.setTitle("Simple Calc - Presentation-Model"); presentation.setVisible(true); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
// structure/presentation-model/CalcViewController.java // Fred Swartz - December 2004 // GUI Organization - GUI independent of model. // // GUI subclasses JFrame and builds it in the constructor. // // The GUI creates a calculator model object, but knows nothing // about the internal implementation of the calculator. import java.awt.*; import java.awt.event.*; import javax.swing.*; public class CalcViewController extends JFrame { //... Constants private static final String INITIAL_VALUE = "1"; //... The Model. private CalcModel m_logic; //... Components private JTextField m_userInputTf = new JTextField(5); private JTextField m_totalTf = new JTextField(20); private JButton m_multiplyBtn = new JButton("Multiply"); private JButton m_clearBtn = new JButton("Clear"); /** Constructor */ CalcViewController() { //... Set up the logic m_logic = new CalcModel(); m_logic.setValue(INITIAL_VALUE); //... Initialize components m_totalTf.setText(m_logic.getValue()); m_totalTf.setEditable(false); //... Layout the components. JPanel content = new JPanel(); content.setLayout(new FlowLayout()); content.add(new JLabel("Input")); content.add(m_userInputTf); content.add(m_multiplyBtn); content.add(new JLabel("Total")); content.add(m_totalTf); content.add(m_clearBtn); //... finalize layout this.setContentPane(content); this.pack(); //... Set button listeners. m_multiplyBtn.addActionListener(new MultiplyListener()); m_clearBtn.addActionListener(new ClearListener()); }//end constructor ////////////////////////////////////////// inner class MultiplyListener /** When a mulitplication is requested. * 1. Get the user input number. * 2. Call the model to mulitply by this number. * 3. Get the result from the Model. * 4. Set the Total textfield to this result. * If there was an error, display it in a JOptionPane. */ class MultiplyListener implements ActionListener { public void actionPerformed(ActionEvent e) { String userInput = ""; try { userInput = m_userInputTf.getText(); m_logic.multiplyBy(userInput); m_totalTf.setText(m_logic.getValue()); } catch (NumberFormatException nfex) { JOptionPane.showMessageDialog(CalcViewController.this, "Bad input: '" + userInput + "'"); } } }//end inner class MultiplyListener //////////////////////////////////////////// inner class ClearListener /** 1. Reset model. * 2. Put model's value into Total textfield. */ class ClearListener implements ActionListener { public void actionPerformed(ActionEvent e) { m_logic.reset(); m_totalTf.setText(m_logic.getValue()); } }// end inner class ClearListener } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
// structure/presentation-model/CalcModel.java // Fred Swartz - December 2004 // Model // This model is completely independent of the user interface. // It could as easily be used by a command line or web interface. import java.math.BigInteger; public class CalcModel { //... Constants private static final String INITIAL_VALUE = "0"; //... Member variable defining state of calculator. private BigInteger m_total; // The total current value state. //========================================================== constructor /** Constructor */ CalcModel() { reset(); } //================================================================ reset /** Reset to initial value. */ public void reset() { m_total = new BigInteger(INITIAL_VALUE); } //=========================================================== multiplyBy /** Multiply current total by a number. *@param operand Number (as string) to multiply total by. */ public void multiplyBy(String operand) { m_total = m_total.multiply(new BigInteger(operand)); } //============================================================= setValue /** Set the total value. *@param value New value that should be used for the calculator total. */ public void setValue(String value) { m_total = new BigInteger(value); } //============================================================= getValue /** Return current calculator total. */ public String getValue() { return m_total.toString(); } } |