7

正如我所知,在 MVC 的标准实现中,我们将 Controller 和 Model 传递给 View

但我有点不同意这个想法。我不希望我的视图同时了解控制器和模型(哦不。也许有时视图需要模型,但我确信他可以在不了解控制器的情况下生活)

我认为Controller应该管理View和Model,而Model不需要知道Controller和View;视图不需要知道控制器(我不排除模型,因为视图的某些实现需要知道模型才能监听模型的变化)。所以我的想法是view 不需要知道 controller

1.这是一个例子:

public class MyView implements ButtonClickListener {

    private Controller myController;
    private Button myButton;

    // I commented out the model because we dont need it now 
    // we are talking about using controller in the view

    public MyView(Controller c/*, Model m*/) {
        myController  = c;
        myButton      = new Button(); // lets say that it is "register" button
        myButton.setOnButtonClickListener(this);
    }

    public void setRegisterButtonText(String text) {
        myButton.setText(text);
    }

    @Override
    public void onClick() {
        myController.tellToModelToDoSomething();
    }

}

和控制器:

public MyController implements Controller {

     private Model model;
     private View view;

     public MyController(Model model) {

          this.model = model;
          this.view  = new MyView(this);

     }

     public void tellToModelToDoSomething() {
          model.doSomeActions();
     }


}

2.现在我如何在不通过控制器的情况下查看此实现:

我的观点:

public class MyView {

    private Button myButton;

    public MyView() {
        myButton = new Button();
    }

    public void setRegisterButtonText(String text) {
        myButton.setText(text);
    }

    public void setOnRegisterButtonClick(final Command command) {
        myButton.setOnButtonClickListener(new ButtonClickListener() {
                            @Override
                            public void onClick() {
                                command.execute();
                            }
                         });
    }

}

“命令”界面:

public interface Command {

     void execute(/*also can handle extra params*/);

}

和控制器:

public MyController implements Controller {

 private Model model;
 private View view;

 public MyController(Model model) {

      this.model = model;
      this.view  = new MyView();

      view.setOnRegisterButtonClick(command);

 }

 public void tellToModelToDoSomething() {
      model.doSomeActions();
 }

 private Command command = new Command() {

     public void execute() {
          tellToModelToDoSomething();
     }

 };

}

那么为什么我认为在视图中使用控制器并不好

我们正在混合控制器和视图实现,建立新的依赖关系。

另外我认为 View 应该只包含 VIEWS 和它们的操作(并且使用控制器和他的一些方法已经看起来像逻辑)。

在第一个示例中,视图告诉控制器该做什么。你同意吗?看起来视图控制控制器!

在第二个示例中,控制器控制要做什么,并告诉视图如果单击某个按钮(只有视图知道它将是什么按钮)要做什么

我总是使用第二种方案,但是在阅读了一本关于 mvc 的新书后,说我们需要将控制器传递给视图,我有点困惑。

你能帮我理解为什么我错了并给我看一些例子吗?

4

1 回答 1

11

没有 MVC 标准,因为有很多实现。这是许多教科书中对 MVC 的一种解释:

在这个解释中控制器的定义是它处理来自视图的事件,所以视图必须使用控制器。

在标准 MVC 中,模型包含并公开数据,控制器操作模型并接受来自视图的事件,视图呈现模型并为控制器生成事件。

MVC 被认为是一个事务系统,其中事务由事件发起。交易通常如下所示:

  1. 在视图上生成一个事件(例如单击按钮)。
  2. 事件信息从视图传递到控制器。
  3. 控制器调用模型上的方法来更改它(设置器和其他可能更新某些数据库的操作方法)。

这些第一步代表 VC 链接和 MC 链接。VC 的存在是因为事件从视图传递到控制器以进行处理,而不是视图直接处理它们。存在 MC 链接是因为控制器根据触发的事件更新模型。

从这里开始,有两条路。第一个:

  1. 交易结束。
  2. 另外,模型会触发自己的事件以指示它已更改。
  3. 视图正在侦听模型并接收事件,并更新其模型表示以反映更改。

这第一条路径代表了对 MV 链接的一种解释。MV 链接是 1) 视图从模型中获取其数据的信息,以及 2) 模型告诉视图在修改后进行更新。

第二条路径只有一步:一旦控制器处理了事件,视图会立即更新,只需刷新其所有 UI 元素。对 MV 链接的这种解释是,模型只是将其信息提供给视图,与上面第一条路径中来自 MV 链接的点 #1 相同。

这是针对我描述的 MVC 架构修改的一些代码:

public class MyView implements View, ModelListener {

    private Button myButton;
    private Controller controller;

    public MyView(Controller controller, Model model) {
        myButton = new Button();
        myButton.setOnButtonClickListener(new ButtonClickListener() {
            @Override
            public void onClick() {
                controller.onRegisterButtonClick();
            }
        });
        this.controller = controller;
        model.addModelListener(this);
    }

    public void setRegisterButtonText(String text) {
        myButton.setText(text);
    }

    public void modelUpdated(Model model) {
        // Update view from model
    }
}

和控制器:

public MyController implements Controller {

    private Model model;
    private View view;

    public MyController(Model model) {
        this.model = model;
        this.view  = new MyView(this, model);
    }

    private void manipulateModel() {
        model.doSomeActions();
    }

    public void onRegisterButtonClick() {
        maniuplateModel();
    }
}

然后是模型:

public class MyModel implements Model {
    private List<ModelListener> modelListeners = new ArrayList<ModelListener>();

    public void addModelListener(ModelListener ml) {
        if (!modelListeners.contains(ml)) {
            modelListeners.add(ml);
        }
    }

    public void removeModelListener(ModelListener ml) {
        modelListeners.remove(ml);
    }

    public void doSomeActions() {
        // Do something
        fireUpdate();
    }

    private void fireUpdate() {
        // Iterates backwards with indices in case listeners want to remove themselves
        for (int i = modelListeners.size() - 1; i >= 0; i-- {
            modelListener.modelUpdated(this);
        }
    }
}

ModelListener很简单:

public interface ModelListener {
    void modelUpdated(Model model);
}

这只是一种解释。如果您想在不同部分之间进一步解耦,您应该查看演示、抽象、控制 (PAC) 模式。它比 MVC 更解耦,也非常适合分布式系统。对于简单的 Web、移动、桌面应用程序来说,它是多余的,但是一些客户端/服务器应用程序和大多数云应用程序可以从这种方法中受益。

在 PAC 中,您拥有三个部分,表示、抽象和控制,但抽象和表示(模型和视图)不相互交互。相反,信息只进出控制模块。此外,您可以拥有多个 PAC 子模块,这些子模块只能通过它们的控件相互交互,从而为分布式系统提供良好的模式。基本上,控制模块是任何数据传输的主要枢纽。

本质上,您对 MVC 的解释可能与我或他们的不同。重要的是您选择一种架构模式并遵循它以保持您的代码在未来可维护。你是对的,有一些方法可以进一步解耦 MVC。实际上,您的示例有点像 PAC,但不是删除 VC 链接,而是删除了 MV 链接。

无论如何,遵循一个架构,记录你的架构(这样人们就知道你的解释是什么),不要偏离那个方向。

于 2012-09-17T16:34:44.420 回答