使用Java中的Swing在GUI开发中正确实现MVC模式

首先,我来自MVC的一个很大的PHP背景,当我开始使用PHP时,我浏览了很多次,尽我所能并在PHP中完善我的MVC-Like设计。 很多人都回答了很多帮助我的答案。

但是在Swing中开始GUI开发之后,关于Swing中MVC的答案是完全不同的。 例如,模型也是一种观点? 根据Oracle的建议, TextElementModel在这里没有任何逻辑业务,它所做的只是标记(设置颜色等)和设置数据,如设置文本等。 当我用PHP开发时,没有AbstractModel这样的东西,因为我总是被告知模型不是一个类,或者更多,它是一个处理逻辑业务的整个层。

在PHP中,我使用了服务,数据映射器和域对象,这个惊人的答案提示我在PHP中帮助了我: 如何在MVC中构建模型?

我的尝试

再次阅读之后,我想在Java中做一个类似的事情:

我有ControllerContainer创建所有控制器:

 public class ControllerContainer { private JFrame frame; public ControllerContainer(JFrame rune) { this.frame = frame; } public void initControllers() { Atest test = new Atest(frame); test.registerView("test", new ViewTest(test)); } } 

如您所见,我将带有ViewTest实例的名为“test”的视图添加到控制器,现在它将在框架中可见,并且可以接受输入。

我的Controller类,应该是抽象的,但我还没有把它抽象化:

 public class Controller { private JFrame frame; private Map views = new HashMap(); public Controller(JFrame frame) { this.frame = frame; } protected void registerView(String title, Component c) { this.views.put(title, c); this.frame.add(c); } protected void deregisterView(String title) { this.frame.remove(this.views.get(title)); this.views.remove(title); } protected Component getView(String title) { return this.views.get(title); } } 

还有一个测试控制器:

 public class Atest extends Controller { public Atest(JFrame frame) { super(frame); } public void hit() { ((ViewTest) super.getView("test")).changeColorBlue(); } } 

我的TestView

 public class ViewTest extends JPanel { private final Atest controller; public ViewTest(Atest c) { this.controller = c; setBackground(Color.RED); setLocation(0,0); setSize(300, 300); setLayout(null); JButton b = new JButton("hello"); b.setSize(150, 150); b.setLocation(0,0); b.addMouseListener(new MouseListener() { @Override public void mouseClicked(MouseEvent arg0) { controller.hit(); } @Override public void mouseEntered(MouseEvent arg0) { } @Override public void mouseExited(MouseEvent arg0) { } @Override public void mousePressed(MouseEvent arg0) { } @Override public void mouseReleased(MouseEvent arg0) { } }); add(b); } public void changeColorBlue() { setBackground(Color.BLUE); } } 

问题

如您所见,我的视图创建了一个新按钮,并为其添加了一个鼠标侦听器。 监听器将有权访问控制器以传递输入。 控制器获取输入并更改视图。

基本上控制器立即被迫更新视图,没有任何严肃的逻辑业务,因为在我的情况下不需要它。

根据我上面发布的链接,tereško回答,我如何正确地使用他的想法和Java Swing的建议?

在PHP背景之后,我真的很困惑。

也许我是误解,一切都应该用不同的语言做不同的事情? 但我认为模式应该始终以相同的方式实现。

如果您需要更多信息,请告诉我们。

也许我是误会,一切都应该用不同的语言做不同的事情?

没有误解; 该模式仅以不同方式应用。

正如@ordous的评论和@udalmik的这个答案所指出的,Swing应用程序可能有多个MVC模式的实现。 如此处和此处所述 ,“并非每个交互都需要通过应用程序的控制器。” 相比之下, Web应用程序可能“在视图和控制器之间具有1:1的关系”。

这里引用的Swing可分离模型体系结构 “将每个组件的视图和控制器部分折叠成单个UI(用户界面)对象。” Swing控制器分散在JComponent的后代中,通常位于组件的UI委托中 。 作为一个具体示例, BasicButtonUI包含一个处理用户鼠标交互的BasicButtonListener

几乎在链接中使用了答案 ,但他的控制器扩展JPanel的事实毁了它,完全让我感到困惑。

这可能令人困惑,因为简单的Swing程序可能根本没有明确的控制器。 如本概要所述, 控制器可以直接访问任何相关的视图模型 ; 它还可以监听用户与视图的交互。 该示例旨在说明最简单的此类交互。 仅仅巧合的是,用户与视图组件的交互引起了这种效果。 例如, 此处引用的模拟具有一个ControlPanel视图组件,用于更新应用程序的视图和模型。 DisplayPanel直接侦听需要模型更新的ComponentEvent 。 等等。

然后,您的应用程序的控制器可以自由地专注于应用程序的需求。

@ Marco13详细阐述了这一点,并引用了相关答案中的其他例子。

MVC模式它是一种常见的范例,因此一般来说,pragramming语言之间没有区别。 然而,实现和一些术语有时看起来不同。 在Java Swing中 ,经常会看到以下两种方法:

1.经典MVC

Controller – 侦听用户界面操作,执行相应的模型更新。 可以从不同的 视图中侦听操作。

Model – 表示状态和域逻辑,修改状态的方法。 通知侦听器有关模型更新的信息( 多个视图可以监听更新)。 模型是独立的,对听众及其逻辑一无所知。

视图 – 负责用户界面,UI元素布局,还可以监听模型更新并在需要时更新图形界面。 有一些关于模型的知识,在下面的例子中它知道如何处理“项目”列表。

一些简单的“待办事项”应用程序的设计可能如下所示:

在此处输入图像描述

2. MVP(模型视图演示者)

控制器充当视图模型之间的中介视图变得非常薄,对模型一无所知,只与Controller交互。 Controller侦听ViewModel并执行相应的操作。

在此处输入图像描述

Swing本身增加了一些混乱,因为它使用MVC模式作为其UI组件。 每个UI控件都有一个模型和视图。 设计新的UI组件变得更加容易,但是在整个应用程序设计的“大图”中 – UI控件保留在View层上。