7

私が知っているように、MVC の標準実装では Controller と Model を 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();
     }

 };

}

では、ビューでコントローラーを使用することは良くないと思うのはなぜですか

コントローラーとビューの実装を混在させて、新しい依存関係を作成しています。

また、ビューにはビューとそれらの操作のみを含める必要があると思います(コントローラーと彼のメソッドのいくつかを使用すると、すでにロジックのように見えます)。

最初の例のビューでは、コントローラーに何をすべきかを伝えます。賛成ですか?ビューがコントローラーを制御しているようです!

2番目の例では、コントローラーは何をすべきかを制御し、いくつかのボタン(ビューだけがそれがどのボタンになるかを知っている)がクリックされた場合に何をすべきかをビューに伝えます

私は常に 2 番目のスキームを使用していましたが、mvc に関する新しい本を読んだ後、コントローラーをビューに渡す必要があると書かれていて、少し混乱しました。

なぜ私が間違っているのかを理解し、いくつかの例を示してください。

4

1 に答える 1

11

多くの実装があるため、MVC 標準はありません。多くの教科書で教えられている MVC の解釈の 1 つを次に示します。

この解釈でのコントローラーの定義は、ビューからのイベントを処理するというものであるため、ビューはコントローラーを使用する必要があります。

標準 MVC では、モデルにデータが含まれて公開され、コントローラーがモデルを操作してビューからのイベントを受け取り、ビューがモデルを表示してコントローラーのイベントを生成します。

MVC は、トランザクションがイベントによって開始されるトランザクション システムと見なされます。通常、トランザクションは次のようになります。

  1. ビューでイベント (ボタンのクリックなど) が生成されます。
  2. イベント情報は、ビューからコントローラーに渡されます。
  3. コントローラーは、モデルのメソッドを呼び出してモデルを変更します (一部のデータベースを更新するセッターやその他の操作メソッド)。

これらの最初のステップは、VC リンクと MC リンクを表しています。VC が存在するのは、ビューがイベントを直接処理するのではなく、イベントがビューからコントローラーに渡されて処理されるためです。発生したイベントに応じてコントローラーによってモデルが更新されるため、MC リンクが存在します。

ここから、2 つのパスがあります。最初の1つ:

  1. 取引は終了します。
  2. これとは別に、モデルは独自のイベントを発生させて、変更されたことを示します。
  3. ビューはモデルをリッスンしてイベントを受け取り、そのモデル表現を更新して変更を反映します。

この最初のパスは、MV リンクの 1 つの解釈を表します。MV リンクは、1) モデルからそのデータの情報を取得するビュー、および 2) 変更されたので更新するようにビューに指示するモデルです。

2 番目のパスは 1 つのステップにすぎません。コントローラーがイベントを処理すると、ビューはすべての 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 には、プレゼンテーション、抽象化、およびコントロールの 3 つの部分がありますが、抽象化とプレゼンテーション (モデルとビュー) は相互に作用しません。代わりに、情報は制御モジュールを出入りするだけです。さらに、複数の PAC サブモジュールを制御を通じてのみ相互に作用させることができるため、分散システムの適切なパターンに役立ちます。基本的に、制御モジュールはあらゆるデータ転送のメイン ハブです。

基本的に、あなたの MVC の解釈は、私や彼らの解釈とは異なる場合があります。重要なことは、アーキテクチャ パターンを選択し、それに従って、コードを将来も維持できるようにすることです。そして、MVC をさらに分離する方法があることは間違いありません。実際、あなたの例は PAC に少し似ていますが、VC リンクを削除する代わりに、MV リンクを削除します。

いずれにせよ、アーキテクチャに従い、アーキテクチャを文書化して (人々があなたの解釈を理解できるように)、それから逸脱しないようにします。

于 2012-09-17T16:34:44.420 に答える