3

現在、Java で Blackjack アプリケーションをプログラミングしていますが、MVC アーキテクチャで記述する必要があります。モデル、ビュー、コントローラーはすべて完全にコーディングされており、すべてが完全に機能しています。しかし、リスナーをコンポーネントにアタッチする最良の方法は何か (JButton など) を考えています。

My current design declares all components in the view that need listeners as public final. It then passes the view to the controller. From there, the controller has full reign to access the components and add action listeners. Code example:

public class View extends JFrame {
    public final JButton myBtn1 = new JButton("Button 1");
    public final JButton myBtn2 = new JButton("Button 2");

    public View() {
        //constructor code here....
    }
}

public class Controller {
    private Model myModel;
    private View myView;

    public Controller(Model m, View v) {
        myModel = m;
        myView = v;

        //now add listeners to components...

        myView.myBtn1.addActionListener(new MyActionListener1());
        myView.myBtn2.addActionListener(new MyActionListener2());
    }
}

However, one of my friends has declared all his JButton's with private scope and then made public methods in the view to add action listeners to their respective components. To me, this just seems like a waste of time and only adds unnecessary code. Code example:

public class View extends JFrame {
    private JButton myBtn1 = new JButton("Button 1");
    private JButton myBtn2 = new JButton("Button 2");

    public View() {
        //constructor code here....
    }

    public void myBtn1AddActionListener(ActionListener a) {
        myBtn1.addActionListener(a);
    }

    public void myBtn2AddActionListener(ActionListener a) {
        myBtn2.addActionListener(a);
    }

    //etc etc...
}

public class Controller {
    private Model myModel;
    private View myView;

    public Controller(Model m, View v) {
        myModel = m;
        myView = v;

        //now add listeners to components...

        myView.myBtn1AddActionListener(new MyActionListener1());
        myView.myBtn2AddActionListener(new MyActionListener2());
    }
}

So, given the two scenarios above, which is the better way?

Thanks.

4

4 に答える 4

5

私の現在の設計では、リスナーを必要とするビュー内のすべてのコンポーネントを public final として宣言しています。次に、ビューをコントローラーに渡します。そこから、コントローラーはコンポーネントにアクセスし、アクション リスナーを追加するための完全な権限を持ちます。コード例:

いいえ、不必要にフィールドを公開しないでください。MVC のためにカプセル化を犠牲にするべきではありません。上記の理由により、コンポーネントを公開するべきではありません。代わりに、コントロールが呼び出すことができるパブリック メソッドをビューに与えるか、モデルへのリスナーを介してビューの状態を変更します。コントロールをビューに渡し、ビューをコントロールに渡します。すべての対話は、コンポーネントやフィールドを公開するのではなく、パブリック メソッドを介して行う必要があります。

私がこれを解決した 1 つの方法は、Control のインスタンスを View に渡し、リスナーに匿名の内部クラスを使用し、これらのクラスにコントロール メソッドを呼び出させることです。たとえば、

// inside of view
exitButton.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent evt) {
      if (control != null) {
         control.exitAction();
      }
   }
});
于 2012-04-23T18:16:02.180 に答える
5

注:この回答は私の個人的な意見です。Swing UI を記述し、それをビジネス ロジックに結び付けるための「最良/最も推奨される」方法について、適切な文献を見つける必要があります。しかし、それがわかるまでは、常識と個人的な経験を使用します。

どちらもこれを実装する正しい方法ではないと思います。MVC では、ビューは視覚的な情報をユーザーに提供する単なる部分です。ただし、ボタンを押したときにトリガーされるActionListenerコードは、おそらくビジネスロジックであるため、コントローラーに属するコードです(これは、コードスニペットに基づいて作成した仮定です。ボタンが次のようなUIアクションを実行する場合別のコンポーネントを有効にするには、アクション リスナーをビューに完全に含める必要があります)。

したがって、これらのメソッドをコントローラーで公開します。たとえば、現在ActionListener好きなものがある場合

public void actionPerformed( ActionEvent e ){
  doSomeStuff( UI info, event info );
}

UI infoビューから取得した情報とイベントから取得した情報はどこにありevent info、コントローラーにパブリックメソッドを導入します

public void doSomeStuff( UI info, event info )

ビューからそのメソッドを呼び出します。これには 2 つの大きな利点があります。

  1. コントローラーからビューへの依存関係ではなく、ビューからコントローラーへの依存関係のみがあります。コントローラーにビジネス ロジックが含まれている場合、そのコードを SwingUI で再利用することはよくあります。ここでは、Swing クラスに依存することは望ましくありません。例として、単体テストがあります。コントローラーが UI に依存していない場合は、アプリケーションのコントローラー モデル部分を簡単にテストし、UI を介してこれらの呼び出しを呼び出す場合と同じように、API を使用して同じコード パスをたどることができます。
  2. ActionListenerUI を完全に調整し、コントローラとビューを書き直さなければアタッチできない別のコンポーネントでボタンを置き換えることを決定できます。

編集

私の投稿の上記の部分はまだ有効だと思いますが、トラッシュゴッドの回答で参照されているウィキペディアの MVC ページ(コメントの 1 つで言及されています) を読んだ後、上記は MVC パターンの 1 つの解釈にすぎないことを認めなければなりません。これを Swing アプリケーションに実装する方法。

その Wiki ページを見ると、MVC の 3 つのコンポーネントが (要約) として定義されています。

  • モデル: アプリケーション ドメインの動作とデータを管理します
  • View : モデルを対話に適した形式 (通常はユーザー インターフェイス要素) にレンダリングします。
  • Controller : ユーザー入力を受け取り、モデル オブジェクトを呼び出して応答を開始します

私の解釈/意見/推奨される方法は、1 つのモデルと 1 つのコントローラーを持ち、必要に応じて複数のビューを使用することです (たとえば、ゼロ ビューをテストする場合)。コントローラーはユーザー入力を直接受け取りません (ビューにリスナーを登録するのと同じです) が、ユーザー入力を渡すための API フックを提供します。これは、ユーザー入力を処理できる一種の「抽象コントローラー」を提供しますが、ビューは実際のユーザー入力イベントをコントローラーが理解できるイベント/情報に変換する必要があります。つまり、コントローラーやモデルを変更することなく、MVC のテスト用の「ビュー」側と実際の「ビュー」側を簡単に作成できるということです。

もう 1 つの解釈は、コントローラーとビューの間をより緊密に結合することです (実際に相互に依存している場合)。これは、Swing UI ビューからコマンドライン ビューに切り替える場合、おそらくコントローラーも変更する必要があることを意味します。これは良いですか悪いですか...それは個人的な好みの問題だと思います。

私の元の回答であまり良くなかった唯一のことは、ビジネスロジックをコントローラー部分に配置したことですが、Wikiページにはモデルに配置されていることが明確に記載されています。モデルがデータ アクセス レイヤーにすぎない単純な Ruby on Rails の実験に、おそらく混乱したことでしょう。私の悪い...

于 2012-04-23T18:20:59.303 に答える
1

私は個人的にあなたのスタイルが好きですが、あなたの友人のスタイル (またはそれに類似したもの) は、より「標準的な Java ライク」であることがわかるでしょう。そのため、通常のプログラミング チームでは、より受け入れやすくなります。また、特定のユースケースでボタンを別のボタンに置​​き換えることができるという (考えられる) 利点 (および考えられる落とし穴) もあります。

于 2012-04-23T18:20:32.437 に答える
0

あなたの質問がアーキテクチャ API (現在は実際の API ではない) に関連している場合、どちらの方法も悪いと思います。さらに、結果が良くないため、実際の経験がなく、それを明確に理解する前にパターンを使用しないでください。

于 2012-04-23T18:13:05.383 に答える