MVP观点到底有多愚蠢

MVP观点到底有多愚蠢

本文介绍了MVP观点到底有多愚蠢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力学习MVP,但有些事情让我望而却步;如果Presenter将视图用作界面,则View不能只是一个简单的控件渲染。想象一下,尝试编写一个打字练习游戏,其中单词随机生成到用户界面中,用户必须在屏幕下方输入单词。

I'm trying to learn MVP, but something eludes me; if the Presenter uses the view as an interface, then the View cannot be just a simple rendering of controls. Imagine trying to write a typing-practice game, where words are randomly generated into the UI and the user must type the words as they fall down the screen.

所以视图会有类似的方法:

So the view is going to have methods like:

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将会有负责创建自定义控件。这里省略了很多代码,但希望这足以说明我的意思。示例:

But ultimately the VIEW is going to have to be responsible for creating custom controls. A lot of code is omitted here, but hopefully this is enough to illustrate what I mean. Example:

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实现已经有了逻辑。它维护 WordComponent Map 。我在这里有两个类, WordLayout实现LayoutManager2 WordComponent扩展JLabel (或其他东西,但是甚至更多的代码)。

Already the View implementation has logic going on. It's maintaining a Map of its WordComponents. I have two classes of my own here, WordLayout implements LayoutManager2, and WordComponent extends JLabel (or something else, but that would be even MORE code).

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

In theory, the presenter should know nothing about Swing, so I can unit test with a mock that maybe logs to the console or something. But simply managing the Swing objects is a job into itself. Or, what if I wanted to transform this application into a Tomcat Webpage. Now class ServletView is managing the AJAX calls that move the words around. Which has a dependency on the AJAX framework, which is even more work offloaded to the View.

摘要:是查看实现应该有逻辑管理自己的组件?

Summary: Are View implementations supposed to have "logic" that manage their own components?

后续:我上面写的代码可能甚至不会响应,因为 Model Presenter 没有在Event Dispatch线程上工作(或者,他们是,这可能更糟)。交出显示事件调度线程更新的代码在哪里?或者, Presenter 是否应该在事件发送线程上?

Followup: The code I wrote above probably won't even be responsive, because the Model and the Presenter aren't working on the Event Dispatch thread (or, they are, which is probably worse). Where does the code that hands off display updates to the Event Dispatch thread go? Or, should the Presenter be on the Event Dispatch thread?

编辑:一个这个想法刚刚发生在我身上拥有特定于平台的子演示者 了解实施细节,例如您是使用Swing还是其他。

One idea just occurred to me. Having a platform-specific sub-presenter that is aware of implementation details like whether you're using Swing or something else.

Edit2:还有一个问题,基于@DuncanJones的回答。想象一下,我想把逻辑放在一起,让游戏可以调整大小,并根据新的大小调整一切的大小。该逻辑是在查看,还是在 Presenter

Still another question, based on @DuncanJones answer. Imagine I wanted to put logic to make the game resizeable and scale the size of everything based on the new size. Would that logic be in the View, or in the Presenter?

推荐答案

View组件必须包含足够的逻辑来显示用户的界面。根据所使用的框架,View中可能会有相当多的代码。重要的是确保业务逻辑位于Presenter中。

The View component must contain sufficient logic to display the interface to the user. Depending upon the framework used, there can be quite a bit of code in the View. The important thing is to ensure business logic lies in the Presenter.

关于您的辅助查询,所有Presenter方法都将在EDT上调用视图调用它们(在Swing的情况下)。除非Presenter所要求的操作微不足道,否则我会立即启动后台线程来完成工作。使用 SwingUtilities.invokeLater()完成后,该线程将更新View。

Regarding your secondary query, all Presenter methods will be invoked on the EDT when the View calls them (in the case of Swing). Unless the action required by the Presenter is trivial, I would immediately kick off a background thread to complete the work. That thread will update the View when completed using SwingUtilities.invokeLater().

实际上,为避免被束缚对于Swing,我倾向于将自己的 EventDispatcher 类传递给每个Presenter。这是一个接口,其方法与 SwingUtilities 相同。然后我可以在必要时替换另一个类。

In fact, to avoid being tied to Swing, I tend to pass my own EventDispatcher class to each Presenter. This is an interface with the same methods as SwingUtilities. I can then substitute in a different class if necessary.

旁注:这可以使用JUnit对Presenter进行单元测试很困难,因为Presenter方法(和单元测试)将在后台线程之前完成。我倾向于使用 Executor 构造每个Presenter,负责运行后台线程。然后,在单元测试环境中,我传入一个特殊的 Executor 实现,该实现立即执行 run()方法同一个线程。这可确保单元测试是单线程的。示例:

Side note: this can make unit-testing the Presenter with JUnit difficult, because the Presenter method (and the unit test) will complete before the background thread does. I tend to construct each Presenter with an Executor that is responsible for running the background threads. Then, in a unit test environment, I pass in a special Executor implementation that immediately executes the run() method on the same thread. This ensures the unit tests are single-threaded. Example:

public class SingleThreadExecutor implements Executor {
  @Override
  public void execute(Runnable command) {
    command.run();
  }
}

这篇关于MVP观点到底有多愚蠢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 07:28