在MVC架构中公开Java组件(例如JButton)的最佳方法是什么? [英] What's the best way to expose Java components such as a JButton in an MVC architecture?

查看:57
本文介绍了在MVC架构中公开Java组件(例如JButton)的最佳方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在用Java编程二十一点应用程序,它需要以MVC架构编写.我已经对所有模型,视图和控制器进行了完全编码,并且一切运行正常.但是,我想知道将侦听器附加到组件的最佳方法是什么(例如JButton).

I'm currently programming a Blackjack application in Java and it needs to be written in an MVC architecture. I have all my models, views and controllers fully coded and everything works perfectly. However, I'm wondering what the best way of attaching listeners to components is (e.g, a JButton).

我当前的设计将视图中需要侦听器的所有组件声明为公共final.然后,它将视图传递给控制器​​.从那里,控制器可以完全控制所有组件并添加动作侦听器.代码示例:

My current design declares all components in the view that need listeners as public final. It then passes the view to the controller. From there, the controller has full reign to access the components and add action listeners. Code example:

public class View extends JFrame {
    public final JButton myBtn1 = new JButton("Button 1");
    public final JButton myBtn2 = new JButton("Button 2");

    public View() {
        //constructor code here....
    }
}

public class Controller {
    private Model myModel;
    private View myView;

    public Controller(Model m, View v) {
        myModel = m;
        myView = v;

        //now add listeners to components...

        myView.myBtn1.addActionListener(new MyActionListener1());
        myView.myBtn2.addActionListener(new MyActionListener2());
    }
}

但是,我的一位朋友用私有作用域声明了他所有的JButton,然后在视图中创建了公共方法,以将动作侦听器添加到它们各自的组件中.在我看来,这似乎是在浪费时间,并且只会添加不必要的代码.代码示例:

However, one of my friends has declared all his JButton's with private scope and then made public methods in the view to add action listeners to their respective components. To me, this just seems like a waste of time and only adds unnecessary code. Code example:

public class View extends JFrame {
    private JButton myBtn1 = new JButton("Button 1");
    private JButton myBtn2 = new JButton("Button 2");

    public View() {
        //constructor code here....
    }

    public void myBtn1AddActionListener(ActionListener a) {
        myBtn1.addActionListener(a);
    }

    public void myBtn2AddActionListener(ActionListener a) {
        myBtn2.addActionListener(a);
    }

    //etc etc...
}

public class Controller {
    private Model myModel;
    private View myView;

    public Controller(Model m, View v) {
        myModel = m;
        myView = v;

        //now add listeners to components...

        myView.myBtn1AddActionListener(new MyActionListener1());
        myView.myBtn2AddActionListener(new MyActionListener2());
    }
}

那么,鉴于上述两种情况,哪种方法更好?

So, given the two scenarios above, which is the better way?

谢谢.

推荐答案

注意:此答案是我的个人观点.我仍然需要找到有关编写"Swing UI"并将其与业务逻辑联系在一起的最佳/最推荐"方式的体面文献.但是直到我发现这一点之前,我都会使用常识和个人经验.

Note: this answer is my personal opinion. I still need to find decent literature on the "best/most recommended" way to write Swing UI and tie it to business logic. But until I find that, I use common sense and personal experience.

我会说这两者都不是实现此目标的正确方法.在MVC中,视图只是您向用户提供视觉信息的部分.但是,按下按钮时在ActionListener中触发的代码是属于控制器的代码,因为这很可能是业务逻辑(这是我根据您的代码片段做出的假设.如果您的按钮只是执行UI动作,例如启用另一个组件,动作侦听器应完全包含在视图中.).

I would say neither of the two is the correct way to implement this. In MVC, the view is simply the part where you provide the visual information to the user. However, the code which is triggered in the ActionListener when you press the button is code which belongs in the controller as it is most likely business logic (this is an assumption I make based on your code snippet. If your button just performs a UI action like enabling another component the action listener should be completely contained in the view).

所以我将这些方法在控制器中公开,例如如果您当前有一个ActionListener喜欢

So I would make those methods public in the controller, e.g. if you currently have an ActionListener like

public void actionPerformed( ActionEvent e ){
  doSomeStuff( UI info, event info );
}

其中UI info是从视图获取的信息,而event info是从事件获取的信息,我将在控制器上引入public方法

where UI info is info obtained from the view and event info info obtained from the event, I would introduce the public method on the controller

public void doSomeStuff( UI info, event info )

并从视图中调用该方法.这有两个主要好处:

and call that method from the view. This has 2 major benefits:

  1. 从视图到控制器仅存在一种依赖关系,而从控制器到视图仅存在一种依赖关系.如果控制器包含业务逻辑,则您不太可能要重用该代码以更多地使用SwingUI.在这里不需要依赖Swing类.一个例子可以是单元测试.如果您的控制器不依赖于UI,则可以轻松测试应用程序的控制器模型部分,并通过使用API​​遵循与通过UI调用这些调用相同的代码路径.
  2. 您可以完全调整用户界面,并决定用另一个组件替换按钮,而不必重写ActionListener即可,而不必重写控制器和视图.
  1. There is only a dependency from the view onto the controller, instead of one from the controller to the view. If the controller contains business logic, it is not unlikely that you want to reuse that code for more the a SwingUI. Having a dependency on Swing classes is unwanted here. An example can be unit testing. If your controller does not depend on the UI, you can easily test the controller-model part of your application, and follow the same code paths by using the API as you would when invoking those calls through the UI.
  2. You can adjust your UI completely and decide to replace the button by another component to which you cannot attach an ActionListener without having to rewrite your controller and your view.

编辑

尽管我认为我的帖子的上述部分仍然有效,但我必须承认在阅读

Although I think the above part of my post is still valid, I must admit that after reading the Wikipedia MVC page referred to in trashgod's answer (which he mentioned in one of the comments), the above is only one interpretation of the MVC pattern and how to implement this in a Swing application.

查看该Wiki页面,它将MVC中的三个组件定义为(总结):

Looking at that Wiki page, it defines the three components in MVC as (summarized):

  • 模型:管理应用程序域的行为和数据
  • View :将模型呈现为适合交互的形式,通常是用户界面元素
  • 控制器:接收用户输入并通过对模型对象进行调用来发起响应
  • Model: manages the behavior and data of the application domain
  • View: renders the model into a form suitable for interaction, typically a user interface element
  • Controller: receives user input and initiates a response by making calls on model objects

我的解释/意见/首选方式是拥有一个模型和一个控制器,并且如果需要,可以有多个视图(例如,在测试零视图时).控制器不会直接接收用户输入(这相当于让它在视图上注册侦听器),但是会提供API挂钩来将用户输入传递给用户.这提供了一种可以处理用户输入的抽象控制器",但是视图仍然需要将实际用户输入事件转换为控制器可以理解的事件/信息.因此,这意味着我可以轻松地创建MVC的测试视图"侧以及真实的视图"侧,而无需更改控制器或模型中的任何内容.

My interpretation/opinion/preferred way is to have one model and one controller, and if needed multiple views (or for example in testing zero views). The controller does not receives user input directly (which would be the equivalent of letting it register listeners on the view), but offers API hooks to pass the user input into. This provide a sort of 'abstract controller' which can handle user input, but the view still needs to translate the real user input events into events/information understandable by the controller. So this means I can as easily create a testing 'view' side of the MVC as well as a real 'view' side without having to change anything in my controller or model.

另一种解释是在控制器和视图(它们之间确实相互依赖)之间具有更紧密的耦合.这也意味着如果您决定从Swing UI视图切换到命令行视图,则可能还必须更改控制器.是更好/更差吗?我认为这是个人喜好问题.

Another interpretation would be to have a more tight coupling between controller and view (where they really depend on each other). This would also mean that if you decide to switch from a Swing UI view to a command-line view you probably have to change the controller as well. Is this better/worse ... I think that is a matter of personal taste.

在我最初的回答中,唯一不好的是我在控制器部分中放置了业务逻辑,而Wiki页面清楚地指出了它位于模型中.我可能对一些简单的Ruby on Rails实验感到困惑,因为该模型仅是数据访问层.我的坏人...

The only thing that was not so good in my original answer is that I located business logic in the controller part, while the Wiki page clearly states it is located in the model. I got probably confused by some simply Ruby on Rails experiments where the model was nothing more then a Data Access Layer. My bad ...

这篇关于在MVC架构中公开Java组件(例如JButton)的最佳方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆