MVP 观点到底有多蠢?

2024-03-26

我正在尝试学习 MVP,但有些事情让我困惑;如果Presenter使用视图作为界面,那么View就不能只是控件的简单渲染。想象一下,尝试编写一个打字练习游戏,其中单词是随机生成到 UI 中的,用户必须在单词从屏幕上落下时输入单词。

所以视图将具有如下方法:

public interface View {
    addWord(String word, double x, double y); // or possibly (Word word)
    moveWord(String word, double distance);
    removeWord(String word);
    setScore(int score);
    registerKeyListener(KeyListener listener);
    // other stuff
}

但最终 VIEW 必须负责创建自定义控件。这里省略了很多代码,但希望这足以说明我的意思。例子:

public class SwingView {
    private JPanel thePanel;

    private Map<String, WordComponent> currentWords = new HashMap<>();

    public SwingView() {
        thePanel = new JPanel(new WordLayout());
        // other stuff
    }

    public void addWord(String word, double x, double y) {
        WordComponent newWord = new WordComponent(word);
        currentWords.put(word, newWord);
        Point2D.Double point = new Point2D.Double(x, y);
        thePanel.add(newWord, point);
    }

    public void removeWord(String word) {
        WordComponent theWord = currentWords.get(theWord);
        thePanel.remove(theWord);
    }
}

View 实现已经有了逻辑。它维持着一个Map of its WordComponents。我在这里有两个自己的班级,WordLayout implements LayoutManager2, and WordComponent extends JLabel(或其他东西,但这将是更多代码)。

理论上,演示者应该对 Swing 一无所知,因此我可以使用可能会记录到控制台或其他内容的模拟进行单元测试。但简单地管理 Swing 对象本身就是一项工作。或者,如果我想将此应用程序转换为 Tomcat 网页该怎么办?现在上课ServletView正在管理移动单词的 AJAX 调用。它依赖于 AJAX 框架,这甚至将更多的工作卸载到View.

摘要: 是View实现应该有管理自己组件的“逻辑”吗?

后续:我上面写的代码可能甚至不会响应,因为ModelPresenter不在事件调度线程上工作(或者,它们在事件调度线程上工作,这可能更糟)。将显示更新移交给事件调度线程的代码去了哪里?或者,应该Presenter在事件调度线程上?

Edit:我突然想到一个想法。拥有一个特定于平台的子演示者is了解实现细节,例如您是否使用 Swing 还是其他东西。

Edit2:还有一个问题,基于@DuncanJones 的回答。想象一下,我想要添加逻辑来使游戏可调整大小并根据新大小缩放所有内容的大小。这个逻辑是否存在于View,或在Presenter?


View 组件必须包含足够的逻辑来向用户显示界面。根据所使用的框架,视图中可能有相当多的代码。重要的是要确保商业逻辑在于演示者。

关于辅助查询,当视图调用它们时(在 Swing 的情况下),所有 Presenter 方法都将在 EDT 上调用。除非演示者所需的操作很简单,否则我会立即启动后台线程来完成工作。该线程将在完成后更新视图SwingUtilities.invokeLater().

事实上,为了避免被 Swing 束缚,我倾向于传递我自己的EventDispatcher给每个演示者上课。这是一个与以下方法相同的接口SwingUtilities。如有必要,我可以替换到不同的班级。

旁注:这可能会使使用 JUnit 对 Presenter 进行单元测试变得困难,因为 Presenter 方法(和单元测试)将在后台线程完成之前完成。我倾向于用一个来构造每个 PresenterExecutor它负责运行后台线程。然后,在单元测试环境中,我通过了一个特殊的Executor立即执行的实现run()同一线程上的方法。这确保了单元测试是单线程的。例子:

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

MVP 观点到底有多蠢? 的相关文章

随机推荐

  • 使用指针的数组长度[重复]

    这个问题在这里已经有答案了 数组长度可以使用以下方式计算 arr 1 arr然后简化为 arr 1 arr这进一步简化为1 arr arr 但是 当在与完成内存分配的函数不同的函数中计算长度时 会计算出错误的结果 例如 include
  • 为什么 Typescript 中需要 infer 关键字?

    为什么 Typescript 开发人员创建了infer关键词 根据文件 https www typescriptlang org docs handbook release notes typescript 2 8 html 这是如何使用它
  • ASP.NET MVC - 从 MemoryStream 下载 Excel 文件(损坏的文件)

    我正在尝试使用浏览器中的内置下载来下载 Excel 文件 基本上 在我的控制器中创建 Excel 文件后 下载工作正常 但是当我尝试在 Excel 中打开此文件时 我被告知该文件已损坏 Excel 无法打开文件 Report xlsx 因为
  • 释放从新放置分配的内存

    考虑下面的代码 include iostream include conio h using namespace std class sample private int i public sample int ii 0 i ii cout
  • 打开android studio配置文件时发生OOM错误

    安卓版本 8 0 0 当我调用file list时 如果我打开android studio profiler来监控内存 很容易出现OOM错误 如下 java lang OutOfMemoryError EnsureLocalCapacity
  • .NET Core 初始请求缓慢

    面对创建新的小型服务的任务 我想知道是否有一些最佳实践指南来确保该服务的快速响应时间 包括前 1 3 个请求 首先 我喜欢使用 NET Core 和 webapi 模板 NET Core 6 创建服务 但是创建其中一些后 我注意到服务的初始
  • Java 数组和列表的共同祖先

    在 NET 中 数组和列表都以 Enumerable 作为祖先 因此接受 Enumerable 作为参数的方法可以同时接收数组和列表作为其参数 我想知道Java中是否有类似的东西 不 Java 中没有类似的东西 我通常建议你设计 API 方
  • setTimeOut 和本地函数

    我正在开发 Axe 4 0 我正在尝试在具有本地函数的作业中使用 Object setTimeOut 方法 如中所述msdn 文档 http msdn microsoft com en US library aa857865 28v ax
  • 在类模板中为成员函数定义单个模板,并在成员函数中使用两个模板

    我目前正在学习模板如何在 C 中工作 特别是 我正在查看类模板中的单个成员函数模板 为了理解我的意思 代码如下 foo h template
  • 向光标位置插入元素(表格)

    我想创建一个具有自定义样式的新 Table 元素 并将其附加到文档中的当前光标位置 我发现可以通过以下方式获取当前位置 var cursor DocumentApp getActiveDocument getCursor 返回一个 Posi
  • ASP.Net 中 URL 中的 UrlEncoding Plus(+)

    我正在对一个字符串进行加密和 Base64 处理 一切都运行良好 直到我从 QueryString 集合中检索加密的字符串 加密文本包含一个加号 当我检索加密的字符串时 曾经有加号的地方现在变成了空格 正如您可以想象的那样 这不会解密 我尝
  • 搜索颠覆历史(全文)

    有没有办法对颠覆存储库执行全文搜索 包括所有历史记录 例如 我编写了一个在某处使用过的功能 但后来不需要它 所以我对文件进行了 svn rm d 但现在我需要再次找到它以将其用于其他用途 svn 日志可能会说 删除了未使用的内容 之类的内容
  • 具有可点击区域的可缩放 SVG - Android

    我正在做一个非常简单的应用程序 它需要显示一个包含广义世界地图的 SVG 通过单击城市名称 svg 矩形 我需要显示与该城市对应的另一个 SVG 此外 所有 SVG 都必须支持缩放和平移 我设法让 SVG 支持缩放和平移 效果非常完美 为此
  • Excel 加载项失败并显示 0x8004063E

    我有一个 Excel 添加 它曾经完美地工作 最近 许多客户收到以下错误 在这个问题的最后 环境详情 Windows 7 8 64 位 微软 Office 2013 64 位 Add in是在 net 3 5下编译的 任何帮助将不胜感激 H
  • Scala 模板将样式应用于 inputText 的标签 [Play 2 HTML5 辅助标签]

    我正在使用带有输入助手的 scala 模板 我使用的类属性应用样式
  • C# - Silverlight 中 .NET ArrayList.ToArray(Type) 的替换

    下面是我编写的一个简单方法 非常简化 所以我希望它仍然能够理解要点 用于获取字符串中数组元素的字符串表示形式 并将它们转换为这些值的实际数组 t 是数组的类型 DeserializeArray string sArrayElements o
  • 在 Tomcat 上安装 Sonar 和 Jenkins

    我有一个 tomcat 服务器 我想在上面安装 Jenkins 和 Sonar 我使用的是 debian 发行版 因此我通过 apt get 获得了 tomcat6 和 Jenkins 当我将 jenkins war 复制到 tomcat6
  • python:从程序运行交互式 python shell

    我经常遇到这样的情况 我将编写一个脚本 并且我正在编写脚本的一部分 我想以交互方式使用一些变量 到达该部分需要运行我已经编写的脚本的大部分 在这种情况下 从 shell 内部运行该程序并非易事 我必须以某种方式重新创建该函数的条件 我想做的
  • 为什么这不能是一个原始的?

    我正在摆弄 JavaScript 并注意到this永远不可能是原始的 我在说什么 让我解释 以这个函数为例 function test return typeof this test call Abc object test call 12
  • MVP 观点到底有多蠢?

    我正在尝试学习 MVP 但有些事情让我困惑 如果Presenter使用视图作为界面 那么View就不能只是控件的简单渲染 想象一下 尝试编写一个打字练习游戏 其中单词是随机生成到 UI 中的 用户必须在单词从屏幕上落下时输入单词 所以视图将