MVC - 我需要在视图中使用控制器?(MVC - do I need to use Contro

2019-07-31 15:32发布

据我所知在标准实施的MVC我们通过控制器和模型视图

但我是有点不同意这个观点。 我不希望我的观点了解这两个控制器和模型(哦,不,也许有时需要查看模式,但我敢肯定,他生活中可以没有控制器的知识)

在我看来控制器应管理视图和模型,以及模型不需要了解控制器和视图。 鉴于犯规需要知道控制器(我不排除模式,因为意见一些实现需要了解模型,听取模型的变化)。 所以我的想法是, 鉴于犯规需要了解控制器

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();
     }

 };

}

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

我们在混合控制器和视图实现,使得新的依赖。

此外,我认为,搜索应该只包含视图和操作与他们(和使用控制器和他的一些方法已经看起来像逻辑)。

在第一个例子图告诉控制器做什么。 你同意吗? 它看起来像视图控制控制器!

在第二个例子控制器控制的事,只是说给视图如果一些按钮(仅视图知道它会是什么按钮)做什么点击

我总是用第二个方案,但阅读新一书中关于MVC,是说,我们需要将控制器传递给视图后,我有点有点混乱。

能否请你帮我明白为什么我错了,并告诉我一些例子吗?

Answer 1:

There is no MVC standard, as there are many implementations. Here's one interpretation of MVC that's taught in many textbooks:

The definition of the controller in this interpretation is that it handles events from the view, so the view must use the controller.

In standard MVC, the model contains and exposes data, the controller manipulates the model and accepts events from the view, and the view presents the model and generates events for the controller.

MVC is considered a transactional system, where a transaction is initiated by an event. The transactions typically look like this:

  1. An event (such as a button click) is generated on the view.
  2. The event information is passed from the view to the controller.
  3. The controller calls methods on the model to change it (setters and other manipulation methods which may update some database).

These first steps represent the V-C link and the M-C link. V-C exists because events are passed from view to controller to be processed instead of the view handling them directly. The M-C link exists because the model is updated by the controller according to the event that was fired.

From here, there are two paths. The first one:

  1. The transaction ends.
  2. Separately, the model fires its own events to indicate it has changed.
  3. The view is listening to the model and receives the event, and updates its model representation to reflect the changes.

This first path represents one interpretation of the M-V link. The M-V link is 1) the view getting information from the model for its data, and 2) the model telling the view to update since it has been modified.

The second path is only one step: once the controller has processed the event, the view updates immediately by simply refreshing all of its UI elements. This interpretation of the M-V link is that the model simply provides its information to the view, the same as point #1 from the M-V link in the first path above.

Here's some of your code modified for the MVC architecture I've described:

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
    }
}

And the controller:

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();
    }
}

Then the model:

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 is pretty simple:

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

This is just one interpretation. If you want further decoupling between the different parts, you should look into the Presentation, Abstraction, Control (PAC) pattern. It's more decoupled than MVC, and is great for distributed systems as well. It's overkill for simple web, mobile, desktop applications, but some client/server applications and most cloud applications can benefit from this approach.

In PAC, you have three parts, presentation, abstraction, and control, but the abstraction and presentation (the model and the view) don't interact with each other. Instead, information passes only in and out of the control module. Furthermore, you can have multiple PAC sub-modules that interact with each other only through their controls, lending itself to a good pattern for distributed systems. Basically, the control module is the main hub of any data transfer.

Essentially, your interpretation of MVC may be different from mine or theirs. What matters is that you choose an architectural pattern and follow it to keep your code maintainable in the future. And you're right that there are ways to decouple MVC further. In fact, your example is a little bit like PAC, but instead of removing the V-C link, it removes the M-V link.

In any case, follow an architecture, document your architecture (so people know what your interpretation is), and don't stray from that.



文章来源: MVC - do I need to use Controller in the View?