【问题标题】:Is this bad MVC design?这是糟糕的 MVC 设计吗?
【发布时间】:2013-02-28 18:40:13
【问题描述】:

我想知道这是否不好;让视图了解控制器,以便它可以委托视图中发生的操作等,并让控制器了解视图(这显然是正确的),但是我想知道这是双向关系是否正确?我想在视图中引用控制器,因为我想将所有工作委托给控制器并保持视图清洁。

这是糟糕的设计吗?如果是这样,我可以做些什么不同的事情并仍然达到相同的效果?

控制器:

public class Controller {

    private View view;

    public Controller() {
        view = new View(this);
    }

    public void doSomeButtonAction() {
        // More code...
    }
}

查看:

public class View implements ActionListener {

    private Controller controller;
    private Button button;

    public View(Controller controller) {
        this.controller = controller;

        // Code for initializing button reference etc.
    }

    @Override
    public void actionPerformed(ActionEvent event) {
        controller.doSomeButtonAction();
    }    
}

【问题讨论】:

  • 这看起来和它应该的完全一样。视图如何知道控制器?
  • 您可以通过控制器中的“视图”引用开始访问“getters”,然后在控制器中附加事件侦听器等。那么视图现在需要有一个参考。所以,是的,视图可以在不知道控制器的情况下存在。
  • 它是可重用的组件吗?视图在编译时定义其按钮的实际作用并没有本质上的“坏”,而不仅仅是它们存在并在运行时等待从其他人那里学习它们的作用。 “此按钮保存该行数据”是有效的视图级别规范。 “这个按钮存在并且如果有人注册一个监听器可能会做一些事情”没有那么有用:)。为了它而添加另一层抽象只会使其他所有内容变得更加难以阅读!

标签: java model-view-controller


【解决方案1】:

您有一个大致的想法:将逻辑(actionPerformed() 的实现放到控制器中。视图将具有可见的小部件,例如,面板中的按钮。这看起来不太像“MVC”我是“VC”,看不到数据模型。

这里没有足够的代码让我称之为“坏”。

【讨论】:

  • actionPerformed()的逻辑在Controller#doSomeButtonAction()
【解决方案2】:

它不是MVC设计,MVC应该把Model、View和Controller分层分离,才能得到设计模式的好处。

您似乎正在使用 JSF ,因此您的 View 和 Controller 类实际上都是 JSF 中 View 层的一部分。您最好将它们重命名为 PageAction、ViewFinder、ViewFrontController 等。

【讨论】:

  • 控制器应该是三层架构中表示(视图)层的一部分。
  • 我同意这一点。我并不是说控制器不应该出现在演示文稿中。它不应该与您的视图(webapp 中的页面视图)混合,我理解 View 类不是一个视图,实际上是一个演示类,这就是为什么我建议将它重命名为更有意义的东西,如 PageAction、ViewFinder、ViewFrontController 等。跨度>
【解决方案3】:

稍后可能会派上用场的一件事是删除Controller 的构造函数中的依赖项。将视图作为参数传递或使用 setter。

public class Controller {

    private View view;

    public Controller(View view) {
        this.view = view;
    }

    public void doSomeButtonAction() {
        // More code...
    }
}

这样,您的控制器不负责创建View。您的程序本身(例如 Main)将负责创建它所需的 View 实现并在创建 Controller 时注入它。如果您想使用模拟视图或控制器,这也将有助于测试。

您的视图负责用户与程序的交互。当它接收到一些用户输入时,它需要通知一些控制器,所以你必须对它有一个引用。然后View 也应该有一个用于其Controller 字段的设置器。这样您就可以构建两者并相互传递。

【讨论】:

  • 好的,谢谢,这不是答案,但这是一个很好的提示:)
  • Is this bad design, if so what could I do differently and still achieve the same?
【解决方案4】:

意见会有所不同,但是,我喜欢将模型设计为应用层中的顶级客户端,这意味着仅由容器(应用服务器 + 任何框架)调用,当然不是由视图或模型。为了清晰起见,我远离视图组件在语言级别直接与控制器对象对话,而是通过协议使其通过容器。因此,如果网页需要向 Java servlet 提供额外的请求,而不是直接调用 servlet,而是向服务器提交 HTTP(或任何其他协议)请求,并让服务器将其路由到适当的控制器组件。这样一来,您就可以在 MVC 的不同组件之间建立一个抽象层,这意味着您可以将一个组件与另一个组件解耦,并且可以更轻松地替换一个组件,同时在需要时尽量减少对其他组件的影响。

所以我的回答是肯定的,视图与控制器对话是不好的。事实上,我喜欢在设计 MVC 时完全依赖 inversion of control,即没有组件直接访问另一个组件,而是有一个由容器管理的抽象层。

【讨论】:

    【解决方案5】:

    指定特定按钮执行的 功能是视图级别的问题。控制器负责提供如何,但它不会向上告诉视图它的按钮应该做什么。视图可以“知道”“这是一个调用保存操作的按钮”。视图的全部目的是将人工输入转化为软件操作!

    如果您想要可重用的组件,您当然可以在其中添加另一层抽象,但是分配按钮执行的操作的代码在概念上仍然是“视图”的一部分,无论您将其粘贴到何处。

    【讨论】:

      猜你喜欢
      • 2012-09-06
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      相关资源
      最近更新 更多