2010-12-12 8 views
3

Ich habe eine funktionierende Java-Bean-Anwendung mit 3 Feldern, wo Feld eins Grenze von Modulo nach Subtraktion Feld 3 von Feld 2. Alles funktioniert gut, aber jetzt wurde ich informiert, dass meine App in MVC neu geschrieben werden sollte wo 3 Eingänge auch Ansichten sind. Die Frage ist also - wohin wohin? Und was sollte das Modell sein?Umschreiben App MVC Stil

import java.io.Serializable; 
import java.awt.*; 
import java.awt.event.*; 
import java.beans.*; 
import javax.swing.*; 

public class Main{ 
    public Main(){ 
     Values val1 = new Values(); 
     Values val2 = new Values(); 
     Limitator changer = new Limitator(val1, val2); 
     Values val3 = new Values(); 
     Input in1 = new Input(); 
     Input in2 = new Input(); 
     Input in3 = new Input(); 
     val1.addPropertyChangeListener(in1); 
     val2.addPropertyChangeListener(in2); 
     val3.addPropertyChangeListener(changer); 
     val1.addVetoableChangeListener(changer); 
     val2.addVetoableChangeListener(changer); 
     GUI frame = new GUI(in1, in2, in3, val1, val2, val3); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args){ 
     Main argh = new Main(); 
    } 
} 

class Input extends JTextField implements PropertyChangeListener{ 
    private static final long serialVersionUID = 1L; 

    public Input(){ 
     this("0"); 
    } 

    public Input(String txt){ 
     super(txt); 
    } 

    @Override 
    public void propertyChange(PropertyChangeEvent evt) { 
     Integer newVal = (Integer) evt.getNewValue(); 
     setText("" + newVal); 
    } 
} 

class GUI extends JFrame implements ActionListener{ 
    private static final long serialVersionUID = 1L; 
    private Values val1; 
    private Values val2; 
    private Values val3; 
    private Input in1; 
    private Input in2; 
    private Input in3; 

    public GUI(Input in1, Input in2, Input in3, Values val1, Values val2, Values val3){ 
     this.setTitle("Beansy!"); 
     this.setPreferredSize(new Dimension(150, 110)); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.val1 = val1; 
     this.val2 = val2; 
     this.val3 = val3; 
     this.in1 = in1; 
     this.in2 = in2; 
     this.in3 = in3; 
     Container con = new Container(); 
     con.setLayout(new BoxLayout(con, BoxLayout.Y_AXIS)); 
     in1.addActionListener(this); 
     in2.addActionListener(this); 
     in3.addActionListener(this); 
     con.add(in1); 
     con.add(in2); 
     con.add(in3); 
     this.add(con); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     int tmp = 0; 
     if(e.getSource()==in1){ 
      try{ 
        tmp = Integer.parseInt(in1.getText()); 
      } catch (NumberFormatException e0){ 
       JOptionPane.showMessageDialog(null, "Numbers only!", "Error", JOptionPane.ERROR_MESSAGE); 
       in1.setText(val1.getValue()+""); 
      } 
      try { 
        val1.setValue(tmp); 
      } catch (PropertyVetoException e1) { 
       JOptionPane.showMessageDialog(null, e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); 
       in1.setText(val1.getValue()+""); 
      } 
     } 
     else if(e.getSource()==in2){ 
      try{ 
       tmp = Integer.parseInt(in2.getText()); 
      } catch (NumberFormatException e0){ 
       JOptionPane.showMessageDialog(null, "Numbers only!", "Error", JOptionPane.ERROR_MESSAGE); 
       in2.setText(val2.getValue()+""); 
      } 
      try { 
       val2.setValue(tmp); 
      } catch (PropertyVetoException e1) { 
       JOptionPane.showMessageDialog(null, e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); 
       in2.setText(val2.getValue()+""); 
      } 
     } 
     else if(e.getSource()==in3){ 
      try{ 
       tmp = Integer.parseInt(in3.getText()); 
      } catch (NumberFormatException e0){ 
       JOptionPane.showMessageDialog(null, "Numbers only!", "Error", JOptionPane.ERROR_MESSAGE); 
       in3.setText(val3.getValue()+""); 
      } 
      try { 
       val3.setValue(tmp); 
      } catch (PropertyVetoException e1) { 
       JOptionPane.showMessageDialog(null, e1.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); 
       in3.setText(val3.getValue()+""); 
      } 
     } 
    } 
} 

class Values implements Serializable{ 
    private static final long serialVersionUID = 1L; 
    private int val = 0; 
    private VetoableChangeSupport veto = new VetoableChangeSupport(this); 
    private PropertyChangeSupport prop = new PropertyChangeSupport(this); 

    public Values(){ 
     this(0); 
    } 

    public Values(int val){ 
     try { 
      setValue(val); 
     } catch (PropertyVetoException e) { 
      JOptionPane.showMessageDialog(null, e.getMessage(), "Error when initializing", JOptionPane.ERROR_MESSAGE); 
     } 
    } 

    public synchronized void addPropertyChangeListener(PropertyChangeListener prop_nu) { 
     this.prop.addPropertyChangeListener(prop_nu); 
    } 

    public synchronized void removePropertyChangeListener(PropertyChangeListener prop) { 
     this.prop.removePropertyChangeListener(prop); 
    } 

    public void addVetoableChangeListener(VetoableChangeListener veto){ 
     this.veto.addVetoableChangeListener(veto); 
    } 

    public void removeVetoableChangeListener(VetoableChangeListener veto){ 
     this.veto.removeVetoableChangeListener(veto); 
    } 

    public int getValue(){ 
     return this.val; 
    } 

    public synchronized void forceValue(int val){ 
     int oldValue = this.val; 
     this.val = val; 
     prop.firePropertyChange("Value", new Integer(oldValue), new Integer(val)); 
    } 

    public synchronized void setValue(int val) throws PropertyVetoException{ 
     int oldValue = this.val; 
     veto.fireVetoableChange("Value", new Integer(oldValue), new Integer(val)); 
     this.val = val; 
     prop.firePropertyChange("Value", new Integer(oldValue), new Integer(val)); 
    } 
} 

class Limitator implements VetoableChangeListener, PropertyChangeListener{ 
    int range; 
    Values val1; 
    Values val2; 

    public Limitator(){ 
     this(0, null, null); 
    } 

    public Limitator(int num){ 
     this(num, null, null); 
    } 

    public Limitator(Values val1, Values val2) { 
     this(0,val1,val2); 
    } 

    public Limitator(int num, Values val1, Values val2) { 
     this.range = num; 
     this.val1 = val1; 
     this.val2 = val2; 
    } 

    @Override 
    public synchronized void vetoableChange(PropertyChangeEvent arg0)throws PropertyVetoException { 
     int nu_val = (Integer)arg0.getNewValue(); 
     int ol_val = (Integer)arg0.getOldValue(); 
     int another_val; 

     if(arg0.getSource()==val1){ 
      another_val = val2.getValue(); 
     }else{ 
      another_val = val1.getValue(); 
     } 

     if(Math.abs(another_val - nu_val) > range){ 
      if(arg0.getSource()==val1){ 
       val1.forceValue(ol_val); 
      } 
      else if(arg0.getSource()==val2){ 
       val2.forceValue(ol_val); 
      } 
      throw new PropertyVetoException("Limit exceeded!!", arg0); 
     } 
    } 

    @Override 
    public synchronized void propertyChange(PropertyChangeEvent evt) { 
     int new_range = ((Integer)evt.getNewValue()).intValue(); 
     this.range = new_range; 
    } 
} 
+1

"Und was sollte das Modell sein?" Fragen Sie sich selbst: Wenn ich diese App auf eine andere Benutzeroberfläche portieren müsste (z. B. webbasiert), müsste ich dann den gesamten Code verwerfen? Gibt es Teile des Codes, die ich noch verwenden könnte? Könnte ich den Code reorganisieren, so dass es beim nächsten Mal einfacher wäre, wenn ich auf eine andere Benutzeroberfläche portieren müsste? –

+0

gute Fragen.Problem ist, dass es hier kein echtes Modell gibt. Ich denke nur an einen Wrapper für Limiter und Werte. – DevAno1

+0

Hier ist ein MVC-Beispiel, das einen Ansatz vorschlagen könnte: http://stackoverflow.com/questions/3072979 – trashgod

Antwort

1

Hier einige Informationen, die Sie den genauen Code helfen sollen, ohne Angabe von:

die Logik

Grundsätzlich zu trennen die Argumentation hinter Verwendung des MVC-Entwurfsmusters ist von der Benutzeroberfläche. Die drei Teile können kurz als beschrieben werden:

Modell: Die Kernlogik des Programms.

Ansicht (en): Bits der Benutzeroberfläche, die das Modell (Logik) verwenden, um die richtigen Informationen anzuzeigen.

Controller: Es ist am einfachsten, den Controller als ActionListeners für Ihre Ansicht zu betrachten.

Das "Modell" und die "Ansicht (en)" sind fast immer separate Klassen; Der "Controller" wird oft in die Ansicht (en) integriert, da er manchmal einfach aus ActionListenern besteht.

Hier ist ein Beispiel für eine sehr einfache Anwendung von MVC, um ein einfaches Programm sauberer zu machen. Angenommen, wir haben einen Basisrechner, der durch die folgende Schnittstelle definiert wird:

public class Calc { 
    public int add(int[] nums) {} 
    public int sub(int[] nums) {} 
    public int mult(int[] nums) {} 
    public double div(int[] nums) {} 
} 

Und eine GUI für diesen Rechner, CalcGUI. Unser Ziel ist es, das Modell von der Sicht zu trennen. Wir könnten die MVC und so etwas wie diese ...

public class CalcGUI extends JFrame { 
    private Calc model; 
    private JTextField result; 
    public CalcGUI(Calc model) { 
     this.model = model; 
     // Random GUI setup stuff 
     result = new JTextField(10); 
     ... whatever else you need 
     // Add controllers 
    } 
    // A sample view method that uses the model for logic 
    public void add() { 
     result.setText(model.add(user's numbers)); 
    } 
} 

Beachten Sie, wie die GUI keine Logik in-Bedingungen des Programms der Funktionalität (mathematische Operationen) zu verwenden, benötigt. Das "Modell" Calc-Objekt führt alle Logik für die GUI (Ansicht) aus; Die GUI muss lediglich die Methoden des Modells aufrufen und ihre Rückgabewerte verwenden, um dem Benutzer die richtigen Informationen anzuzeigen.

Eine weitere wichtige Sache ist der CalcGUI-Konstruktor. Beachten Sie, wie es ein "Calc" -Objekt einnimmt. Da Objekte in Java Zeiger sind (referenziert durch Speicheradresse), wird immer das gleiche "Calc" -Objekt verwendet. Dies ist wichtig, wenn Sie Informationen in Ihrem Modell speichern müssen (nicht der Fall in dieser App, aber fast immer der Fall in einem ‚echten‘ app) \

Einige hilfreiche Links für das Erlernen der MVC.

http://www.enode.com/x/markup/tutorial/mvc.html

http://www.roseindia.net/struts/struts/struts2.2.1/mvcdesignpattern.html

http://cristobal.baray.com/indiana/projects/mvc.html

ich hoffe, dass geholfen!