如何实现猜词游戏的MVC模式?

我有一些猜词游戏的工作代码。 但我担心它并不局限于设计规则,尤其是MVC模式。 附加的图像是我目前的GUI 。 我把物品从一个类扔到另一个类,我听说这是一种糟糕的风格。 虽然我同意这一点,但我无法为猜词游戏或通常被称为刽子手的人提出好的MVC模式方法。 主要应用程序将有这样的一些:

 public class Application { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { runApp(); } }); } public static void runApp() { Model model = new Model(); View view = new View(model); //not sure if this correct, some suggest it is valid and some not Controller controller = new Controller(view, model); } } 

我该怎么做? 附图中显示的GUI将是View Class。 这包括所有JButtons, Textfield, borders, labels等。将actionlisteners附加到View类中的JButtons, Textfield, borders, labels

controllerevents传递给model 。 例如,如果单击某些letter buttons ,它将通过该字母“A”被单击modelmodel将向controller发送指令以更新view或者它将直接更新view 。 根据我对MVC模式的理解, model类必须与viewcontroller分开实现和测试。 我不明白我怎么能在这里实现这个目标。 我有完整的代码。 我需要重构以限制MVC模式。 请转达你的建议。 在此处输入图像描述

我认为你感到困惑的一个领域是“责任”。 每个组件负责什么以及它实际可以做什么。

问题不在于您在程序周围传递对象,而是您传递的对象更多地暴露了应用程序的部分内容,而收件人没有业务知道或应该允许操作。

我的意思是,如果您将“按钮”面板传递到“猜测”面板,因为您希望能够在单击按钮时允许“猜测”面板检测到,您已经暴露了“按钮”面板指向您无需实际查看的应用程序区域。

是什么阻止了“猜测”面板移除组件? 没有…

相反,我们应该使用interfaces来确定应用程序的每个部分可以做什么和不能做什么以及可以使用哪些信息。

这是您进入模型的地方。模型确定可用的信息,如何访问以及可能触发哪些事件以通知感兴趣的各方模型已更改。

例如。 您的“按钮”面板会告诉模型用户进行了另一次猜测(响应用户按下按钮)。 然后,该模型将引发一个事件,该事件将通知“猜测”面板发生了更改。 然后“猜测”面板会相应地更新它的状态,向模型询问它所需的信息,以便表示模型的当前状态(就其负责而言)。

你可以看看

  • 代码到接口,按名称和实例数据访问
  • 编程到接口

现在,使用MCV模式,视图必须能够看到模型,控制器必须能够看到视图和模型,而模型并不关心。

控制器正在侦听视图的更改(即用户交互),并将其传递给模型。 该模型触发有关其状态更改的通知,并且视图通过根据需要更新自身来响应这些更改。

例如,使用单击“按钮”面板上的按钮。 “按钮”面板的控制器检测到此事件(可能通过ActionListener ),它处理此操作并更新模型。

该模型更新了它的内部状态并触发某种事件。

“guess”面板检测模型中的这种变化(通过某种类型的监听器)并相应地更新它的视图(更新猜测和模型所指示的图像)。

现在,请记住,Swing不使用纯MCV模式,它的控件(即按钮)既是控制器又是视图,所以在玩这些时要小心……

我将从一个HangManModel interface开始,该interface定义了您要公开的所有属性,例如猜测,“秘密”单词以及可能的错误猜测次数和游戏状态(输赢)。

我还将定义可能已注册到模型的侦听器,该侦听器描述此模型可以生成的事件。 您可以根据自己的需要使用PropertyChangeListener甚至ChangeListener或定义自己的,例如……

 public interface HangManModel { public void addGuess(char guess); public char[] getGuesses(); public String getSecretWord(); public int getState(); // running, win or lose public void addChangeListener(ChangeListener listener); public void removeChangeListener(ChangeListener listener); } 

现在这仅仅是一个例子 ,就个人而言,我可能会隐瞒秘密词并揭露它的属性(例如它的长度)。 你也可能想为秘密词提供一个setter,所以模型可以重置……

这将代表您的应用程序的“核心”,围绕此,您将构建您的视图和控制器。

编辑:MVC(netbeans项目,由我制作)的工作示例可在此处 下载或在 此处 下载 。 谁不知道netbeans:在dist中是可执行的.jar文件,在src中是源。 它显示了具有两个不同视图的MVC模式。 在左侧,您可以左键或右键单击以创建圆形或方形,在右侧,您可以在表格中看到这些正方形和圆形。 您可以在表格中更改方形或圆形的值(如大小或位置),并将其更新为更新视图的模型,因此在左侧可以看到该方形或圆形如何移动或resize。

你有很好的方法,但你有一些错误。 这是一个基本的,简单的MVC模型:

在此处输入图像描述

在这里你可以看到, model不会向controller发送任何东西。

如何构建MVC应用程序? Mabye最好从model开始。 除输入/输出处理外, model应具有所有内容。 所有的数据,所有的逻辑。

所以你应该有3个主要类:Controller,View,Model。

例如,您只需使用按钮创建表单,在每个匹配中将一个“A”字母添加到表单的中间。

View类中,您有update方法,它将“A”字母的数量绘制和/或重新绘制到表单中。

当您点击按钮时,它会跳转到方法buttonClicked 。 这会在控制器上调用方法,说控制器发生了什么。 控制器看到并操纵模型中的数据(在此示例中调用方法addA )。 在此之后,模型应该知道他已被更改,因此他在连接的视图类上调用update方法,重新绘制在窗体中间打印的“A”的计数。

加成

一个模型可以有多个视图! 我们可以添加一个视图,在窗体的左上角打印使用的“A”的数量。 模型可以有视图列表而不仅仅是视图,当更改时,他只更新所有视图。

伪代码

 public class Application { private Model model = new Model(); private Controller controller = new Controller(); private View view = new View(); public Application(){ model.registerView(view); controller.registerModel(model); view.registerController(controller); } } 

Interestion问题…到目前为止,我听说过在桌面应用程序中使用的MVP和MVVM设计模式,但我从未见过这类应用程序的MVC。 但是,我刚刚接受了Spring MVC(最好的java Web框架)并尝试将其应用于桌面应用程序。

  1. 我会创建一个前端控制器来处理应用程序的所有事件。
  2. 该控制器获取一个事件并将其发送到EventResolver。
  3. EventResolver返回一个方法和类的名称或类似内容,它将向前端控制器发挥“控制器”角色。
  4. 在前端控制器创建此类的实例并调用方法之后。
  5. 在方法体中,您调用一些业务逻辑并将ViewResolver的模型和id返回到前端Controler。 6前控制器再次分析结果并调用一个认可的ViewResolver。

是的,这就是Spring MVC的工作方式,我只是复制了它)但是为什么不使用最好的!

有许多不同风格的MVC,但它们都有着相同的总体思路。

首先要理解的是模型的确切含义。 模型的工作是处理所有逻辑代码。 因此,在这种情况下,模型将跟踪猜测的字母,要猜的是什么,游戏是否结束,以及棍子人显示了多少件。

基本上,您应该能够从函数调用到模型中完整地模拟游戏。

有几种方法可以将信息从模型传递到视图。 视图可以定期轮询模型以查看是否有任何更新。 这种方法不是很优雅。 对于小规模项目通常有效的简单方法是将View对象传递给Model对象,并且只要模型中发生任何更改,就刷新视图中的所有内容。 对于较小的UI来说,做这件事并没什么大不了的。 最后,您可以创建一个监听器注册系统(Observer模式),以使View的特定部分订阅模型中的特定事件。 这个方法就是我为更大的UI项目所做的。

控制器的工作是将用户输入传递给模型。 因此,控制器和视图通常可以在同一个类中定义。 这没关系! 让JButton有一个直接调用模型的click方法,而不是告诉某些Controller类将它传递给模型,这要好得多。