重写应用程序MVC风格

发布于 2024-10-07 13:27:10 字数 7366 浏览 3 评论 0原文

我有一个具有 3 个字段的工作 java beans 应用程序,其中字段 1 在从字段 2 中减去字段 3 后设置模数限制。一切都工作正常,但现在我被告知我的应用程序应该重写为 MVC,其中 3 个输入也是视图。所以问题是——什么要搬到哪里?模型应该是什么?

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;
    }
}

I have a working java beans application with 3 fields, where field one sets limit of modulo after subtracting field 3 from field 2. Everything was working fine but now I was informed that my app should be rewritten to MVC where 3 inputs are also views. So question is - what to move where ? And what should be the model ?

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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

旧情别恋 2024-10-14 13:27:10

以下是一些应该有所帮助的信息,但无需提供确切的代码:

基本上,使用 MVC 设计模式背后的原因是将逻辑与 UI 分开。这三个部分可以简单描述为:

模型:程序的核心逻辑。

视图:使用模型(逻辑)来显示正确信息的 UI 部分。

控制器:最容易将控制器视为视图的 ActionListener。

“模型”和“视图”几乎总是独立的类; “控制器”通常被合并到视图中,因为它有时只包含添加动作监听器。

下面是一个使用 MVC 使简单程序变得更简洁的非常基本应用程序的示例。假设我们有一个基本计算器,由以下接口定义:

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

以及该计算器的 GUI,CalcGUI。因此,我们的目标是将模型与视图分开。我们可以使用 MVC 等类似的东西...

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));
   }
}

请注意 GUI 如何不需要使用程序功能(数学运算)方面的任何逻辑。 “模型”Calc 对象执行 GUI(视图)的所有逻辑; GUI 需要做的就是调用模型的方法并使用其返回值向用户显示正确的信息。

另一个需要注意的重要事项是 CalcGUI 构造函数。请注意它如何接收“Calc”对象。由于对象是 Java 中的指针(通过内存地址引用),因此将始终使用相同的“Calc”对象。如果您需要在模型中存储信息(此应用程序中并非如此,但“真实”应用程序中几乎总是如此),这一点非常重要。\

学习 MVC 的一些有用链接:

< a href="http://www.enode.com/x/markup/tutorial/mvc.html" rel="nofollow">http://www.enode.com/x/markup/tutorial/mvc.html< /a>

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

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

我希望有所帮助!

Here's some information that should help, without giving you the exact code:

Basically, the reasoning behind using the MVC design pattern is to separate the logic from the UI. The three parts can be briefly described as:

Model: The core logic of the program.

View(s): Bits of the UI that utilize the model (logic) to display the right info.

Controller(s): It's easiest to think of the controller as the ActionListeners for your View.

The "Model" and the "View(s)" are nearly always separate classes; the "Controller" is often incorporated into the View(s), since it sometimes simply consists of adding ActionListeners.

Here's an example of a very basic application of using MVC to make a simple program cleaner. Suppose we have a basic calculator, defined by the following interface:

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

And a GUI for that calculator, CalcGUI. So, our goal is to keep the model separate from the view. We could use the MVC and so something like this...

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));
   }
}

Notice how the GUI doesn't need to use any logic in-terms of the program's functionality (math operations). The "model" Calc object does all the logic for the GUI (view); all the GUI needs to do is call on the model's methods and use its return values to display the proper information to the user.

Another important thing to note is the CalcGUI constructor. Notice how it takes in a "Calc" object. Since Objects are pointers in Java (referenced by memory address), the same "Calc" object will always be used. This is important if you need to store information in your model (not the case in this app, but almost always the case in a 'real' app).\

Some Helpful Links for Learning the 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

I hope that helped!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文