在 MVC 架构中公开 Java 组件(例如 JButton)的最佳方式是什么?

2024-03-17

我目前正在用 Java 编写一个 Blackjack 应用程序,它需要用 MVC 架构编写。我的所有模型、视图和控制器都已完全编码,一切都运行良好。但是,我想知道将侦听器附加到组件的最佳方法是什么(例如 JButton)。

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

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 声明为私有范围,然后在视图中创建公共方法以将操作侦听器添加到各自的组件中。对我来说,这似乎是浪费时间,而且只会添加不必要的代码。代码示例:

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

那么,考虑到上述两种情况,哪种方法更好呢?

Thanks.


注:本回答仅代表我个人观点。我仍然需要找到有关“最佳/最推荐”方式的不错的文献来编写 Swing UI 并将其与业务逻辑联系起来。但在我找到这一点之前,我会运用常识和个人经验。

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

所以我会在控制器中公开这些方法,例如如果您目前有ActionListener like

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

where UI info是从视图中获取的信息并且event info从事件中获取的信息,我将在控制器上引入公共方法

public void doSomeStuff( UI info, event info )

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

  1. 仅存在从视图到控制器的依赖关系,而不是从控制器到视图的依赖关系。如果控制器包含业务逻辑,那么您很可能希望在 SwingUI 之外重用该代码。这里不需要依赖 Swing 类。一个例子是单元测试。如果您的控制器不依赖于 UI,您可以轻松测试应用程序的控制器模型部分,并使用 API 遵循与通过 UI 调用这些调用时相同的代码路径。
  2. 您可以完全调整您的 UI,并决定用另一个您无法附加的组件来替换该按钮ActionListener无需重写您的控制器和视图。

Edit

虽然我认为我的帖子的上述部分仍然有效,但我必须承认,在阅读完维基百科 MVC 页面 http://en.wikipedia.org/wiki/Model-view-controller在trashgod 的回答中提到(他在其中一条评论中提到过),上面只是对MVC 模式以及如何在Swing 应用程序中实现它的一种解释。

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

  • Model:管理应用程序域的行为和数据
  • View:将模型渲染成适合交互的形式,通常是用户界面元素
  • 控制器:接收用户输入并通过调用模型对象来发起响应

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

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

我原来的答案中唯一不太好的地方是我将业务逻辑定位在控制器部分,而 Wiki 页面明确指出它位于模型中。我可能对一些简单的 Ruby on Rails 实验感到困惑,其中模型只不过是一个数据访问层。我的错 ...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 MVC 架构中公开 Java 组件(例如 JButton)的最佳方式是什么? 的相关文章

  • 删除列表视图项目之间的间距

    我正在尝试在 Android 中制作一个包含图像的 ListView 我希望图像在列表中彼此相对 但我似乎无法消除间距 这是我的 listview xml
  • 区域设置的 Java 日期格式

    我怎样才能找到DateFormat对于给定的Locale DateFormat getDateInstance int Locale 例如 import static java text DateFormat DateFormat f ge
  • 使用递归查找数组中的最大值

    对于我被要求解决的问题之一 我使用 for 循环找到了数组的最大值 所以我尝试使用递归来找到它 这就是我想到的 public static int findMax int a int head int last int max 0 if h
  • 如何反编译混淆的java程序以避免类/包名称冲突

    我想反编译一个java程序并重新编译派生的 混淆的 源代码 我解压了 jar 存档并得到了如下目录结构 com com foo A com foo A A class com foo A B Class com foo B A class
  • 如何在中等规模的 Rails 应用程序中组织控制器?

    我正在开发一个具有相当多相关模型的应用程序 并且想听听一些关于如何最好地组织控制器的意见 以下是我一直在考虑的一些选择 1 为控制器命名空间 例如 有一个controllers admin 目录和一个controllers public 目
  • 如何在 El Capitan (OS X 10.11) 中设置 Android Studio?

    全新安装 El Capitan 10 11 尝试安装 Android Studio 版本 1 21 Error Android Studio was unable to find a valid JVM Please download it
  • TreeSet 给出不正确的输出 - Java8

    在处理树集时 我发现了非常奇怪的行为 根据我的理解 以下程序应该打印两行相同的行 public class TestSet static void test String args Set
  • 比 O(n) 更好的范围交集算法?

    范围交集是一个简单但不平凡的问题 已经回答过两次了 查找数字范围交集 https stackoverflow com questions 224878 find number range intersection 比较日期范围 https
  • 字符串文字的行为令人困惑

    下面的代码中字符串文字的行为非常令人困惑 我可以理解第 1 行 第 2 行和第 3 行是true 但为什么是第 4 行false 当我打印两者的哈希码时 它们是相同的 class Hello public static void main
  • “找不到符号”或“无法解析符号”错误是什么意思?

    请解释以下有关 找不到符号 无法解析符号 或 找不到符号 错误 Java 中 的信息 他们的意思是什么 哪些因素会导致它们 程序员如何修复它们 这个问题旨在对 Java 中的这些常见编译错误进行全面的问答 0 这些错误之间有什么区别吗 并不
  • Android文件上传器与服务器端php

    我几个小时以来一直在寻找解决方案 但找不到任何解决方案 基本上 我想从我的 Android 设备上传文件到 http 网站 但是 我不知道如何做到这一点 我在设备上使用java 并且我想在服务器端使用PHP 我只想上传文件 而不是在服务器上
  • 在 Java 中从 Json 字符串中提取字段

    我正在尝试从以下 Json 字符串中提取每个 company id 的 id String test company id 4100 data drm user id 572901936637129135 direct status id
  • HTML 解析和删除锚标记,同时使用 Jsoup 保留内部 html

    我必须解析一些html并删除锚标记 但我需要保留锚标记的innerHTML 例如 如果我的 html 文本是 String html div p some text a href some link text a p div 现在我可以解析
  • Java HashSet 具有自定义相等标准? [复制]

    这个问题在这里已经有答案了 我一直在寻找类似于 Java TreeSet 在实例化时接收自定义比较器的能力 因此我不需要使用对象的默认相等 和哈希码 标准 我能想到的最接近的方法是将我的对象包装在一个私有的自定义类中 但这看起来很老套 这最
  • GSON 预期为 BEGIN_ARRAY,但实际为 BEGIN_OBJECT

    当我仅收到列表中的一项时 我收到此错误 我在服务器端 REST Web 服务中使用 Jersey 只有当列表返回一个元素并且它具有0 elements I get java lang NullPointerException但是当它有多个时
  • Spring 如何在登录网址上设置动态前缀

    我有一个始终以动态前缀开头的 Spring 应用程序 这是因为我需要该前缀来进行一些内部配置 问题是 当我尝试设置登录页面时 无法传递该前缀并使其工作 如何为我的登录页面设置动态前缀 这是我的 AppController 的一部分 我在其中
  • 正确使用Optional.ifPresent()

    我正在尝试理解ifPresent 的方法OptionalJava 8 中的 API 我有一个简单的逻辑 Optional
  • 滚动文件实现

    我一直很好奇滚动文件是如何在日志中实现的 如何开始用任何语言创建一个文件写入类 以确保不超过文件大小 我能想到的唯一可能的解决方案是 write method size file size size of string to write i
  • 当将 Eclipse 与 FindBugs 一起使用时,您可以将错误标记为非错误并将其从错误列表中删除吗?

    FindBugs 在我的代码中发现了潜在的错误 但这不是一个错误 是否可以将此事件标记为 不是错误 并将其从错误列表中删除 我已经非常清楚地记录了为什么每种情况都不是错误 例如 类实现类似的接口 它有compareTo方法 然而 我没有重写
  • 当考虑性能时如何从文件中读取整数?

    我正在 CodeEval 上执行一些任务 基本上任务非常简单 打印出从文件中读取的所有整数的总和 我的解决方案如下 import java io File import java io IOException import java io

随机推荐