3 秋千应用设计:哪个是最好的?[已关闭]

我在桌面应用程序开发方面很陌生,今年夏天我有一个非常大的项目。问题是代码必须非常清晰,所以当我更新它时,我不会遇到(太多)麻烦。

因此,我想要一个很好的“关注点分离”。对我来说,最困难的部分是视图-控制器分离。

现在,我读了很多教程,讨论等。我以3种不同的方式设计了一个迷你应用程序。该应用程序很简单:单击将标签转换为“Hello world”的按钮。

您如何看待这3种设计?

有没有更好的设计来满足我的期望?

设计 1

视图1.java :

public View1() {
    initComponents();
    this.controller = new Controller1(this);
}

private Controller1 controller;

public void updateLabel(String message){
    this.jLabel1.setText(message);
}

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
    this.controller.doSomething();
}

private void initComponents() {
...
jButton1.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton1ActionPerformed(evt);
        }
    });
...}

控制器1.java :

public class Controller1 {
    public Controller1(View1 v){
        this.view = v;
    }

    public void doSomething(){
        this.view.updateLabel("Hello world");
    }

    private View1 view;
}

设计 2

视图2.java :

public View2() {
        initComponents();
        this.controller = new Controller2(this);

        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                controller.doSomething();
            }
        });
    }
    public void updateLabel(String message){
        this.jLabel1.setText(message);
    }
    private Controller2 controller;
  ...

}

控制器2.java :

public class Controller2 {

        public Controller2(View2 v){
            this.view = v;
        }

        public void doSomething(){
            this.view.updateLabel("Hello world");
        }

        private View2 view;
}

设计 3

视图3.java :

public View3() {
        initComponents();
        this.controller = new Controller3(this);
        this.jButton1.addActionListener(this.controller.listener);
    }
    private Controller3 controller;
    public void updateLabel(String message){
        this.jLabel1.setText(message);
    }
...}

控制器3.java :

public class Controller3 {

    public Controller3(View3 v){
        this.view = v;
        this.listener = new MyListener(v);
    }

    private View3 view;
    public MyListener listener;
}

我的Listener.java :

public class MyListener implements ActionListener{
    private View3 view;

    public MyListener(View3 v){
        this.view = v;
    }

    public void actionPerformed(java.awt.event.ActionEvent evt) {
                this.view.updateLabel("Hello world");
            }
}

答案 1

我不喜欢这些设计中的任何一个。您正在将控制器与视图紧密耦合。假设您希望将来更改控制器实现,因此您必须进入所有类并更改类。相反,你应该让它注射。有很多库可以通过GuiceSpring等注释为你做到这一点,但我不会去那些。这是一个更好的设计。

public class View{
private Controller controller;
   public View(Controller controller) {
       this.controller = controller;
   }
}

这是一个更干净的设计,因为视图不必知道控制器的实现是什么。您可以稍后创建一个子类并改为传递该子类。

所以现在有了上面的设计,我认为你可以看到你不应该把视图传递给控制器。这又是耦合,这是不好的。相反,您可以传递一个 onCallback 类,该类将在完成后执行。这是代码来掩盖它

jButton1.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
            controller.doSomething(new Runnable(){
                    public void run(){
                        updateLabel("Hello world");
                    }               
           });
       }
});

然后在你的控制器做

public void doSomething(Runnable callback){
   // do work
   SwingUtilties.invokeLater(callback);
}

如果你仔细看,我所建议的就是消除任何类型的耦合。视图不应要求控制器,而应提供。控制器不应该知道它应该只执行回调的视图。这很重要,因为如果您决定不使用 Swing,那么您就不会在控制器中拥有 Swing 软件包的所有这些依赖项。

希望这一切都有帮助!


答案 2

决定哪种模式最好很大程度上取决于你正在解决的问题。Swing 已经是一个 MVC 框架,因此您必须考虑在其上添加另一层间接层是否值得付出努力。

由于你是UI编程的新手,我建议你先把系统的一个行走的骨架放在一起,然后根据你从中学到的东西,决定你的架构。设计良好的体系结构使测试和重用组件变得容易。MVPMVVM 是 UI 的两种众所周知的设计模式方式。

对于您的玩具问题,您可以实现MVP或MVVM,就像我在下面所做的那样。请记住,您通常还会在每个接口之间使用接口,如果可以更改,则会在 Model 上具有观察者。

最有价值球员

public class Model {
    public String getWhatIWantToSay() {
        return "Hello World";
    }
}

public class Presenter implements ActionListener {
    private final View view;
    private final Model model;
    public Presenter(Model model, View view) {
        this.model = model;
        this.view = view;
        view.addButtonListener(this);
    }
    public void actionPerformed(ActionEvent e) {
        view.setText(model.getWhatIWantToSay());
    }
}

public class View {
    private JButton button = new JButton();
    private JLabel label = new JLabel();
    public void addButtonListener(ActionListener listener) {
        button.addActionListener(listener);
    }
    public void setText(String text) {
        label.setText(text);
    }
}

MVVP

public class ModelView extends Observable {
    private final Model model;
    private String text = "";

    public ModelView(Model model) {
        this.model = model;
    }

    public void buttonClicked() {
        text = model.getWhatIWantToSay();
        notifyObservers();
    }
}

public class View implements Observer {
    private JButton button = new JButton();
    private JLabel label = new JLabel();
    private final ModelView modelView;

    public View(final ModelView modelView) {
        this.modelView = modelView;
        modelView.addObserver(this);
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                modelView.buttonClicked();
            }
        });
    }

    public void update(Observable o, Object arg) {
        label.setText(modelView.text);
    }
}

推荐