2017-02-24 7 views
1

MVPデザインパターンを使用してJavaでGUIアプリケーションを作成しています。 JButtonオブジェクトはViewクラスに属し、ActionListenerオブジェクトはPresenterに属します。私はViewのJButtonオブジェクトをPresenterに公開する簡潔な方法

のように見えるビューにメソッドの束を追加することなく、プレゼンターがビューの JButtons(1)ボタン publicと(2)を作るのいずれかなしに ActionListener Sを追加できるようにする簡潔な方法を探しています
private JButton foo; 
private JButton bar; 

public void addActionListenerToButtonFoo(ActionListener l) { 
    foo.addActionListener(l); 
} 

public void addActionListenerToButtonBar(ActionListener l) { 
    bar.addActionListener(l); 
} 

// (imagine typing 10 more of these trivial functions and having 
// them clutter up your code) 

私は合理的によく働く一つの技術が見つかりました:このラッパーはうまく機能

public class View { 

    class WrappedJButton { 
    private JButton b; 

    public WrappedJButton(String name){ 
     this.b = new JButton(name); 
    } 

    public void addActionListener(ActionListener l) { 
     b.addActionListener(l); 
    } 
    } 

    public final WrappedJButton next = new WrappedJButton("Next"); 
    public final WrappedJButton prev = new WrappedJButton("Previous"); 

    public void setup() { 
    JPanel buttons = new JPanel(); 
    buttons.setLayout(new FlowLayout()); 
    buttons.add(previous.b); 
    buttons.add(next.b); 
} 
} // end view 

class Presenter { 

    public Presenter() { 
    View view = new View(); 

    view.next.addActionListener(event -> { 
     // Respond to button push 
    }); 
    } 
} // end Presenter 

を。ラップされたボタンをpublicにすると、Presenterはそれらを名前で参照できます(これにより、IDEでコード補完を使用できるようになります)。しかし、オブジェクトがWrappedJButtonなので、プレゼンターが行うことができるのは、ActionListenerを追加することだけです。ビューは、プライベートbフィールドを介して「実際の」ボタンをつかむことによって、オブジェクトへの「フル」アクセスを得ることができます。

質問:

  1. より良い/クリーナー解決策はありますか?おそらく何か ビューのbフィールドにアクセスする必要性を排除するでしょうか?
  2. このソリューションを一般化する方法はありますか? カット&ペーストWrappedJButton私が書いた各ビュークラスには?私は WrappedJButtonをインタフェース( の実装)に移動しようとしました。しかし、私がそうすると、Viewは プライベートbフィールドにアクセスできなくなりました。

答えて

0

私は(Presenterが異なるパッケージに存在すると仮定した場合)、パッケージレベルに包まれたボタンを露光することにより、コピー&ペーストWrapperJButtonクラスを避けるために、大丈夫だと思う:

public class WrappedJButton { 
    final JButton b; 

    WrappedJButton(String name){ 
     this.b = new JButton(name); 
    } 

    public void addActionListener(ActionListener l) { 
     b.addActionListener(l); 
    } 
} 

異なりますアプローチは、マップ内のボタンを格納することができます

class ButtonMap<E extends Enum<E>> { 
    private final EnumMap<E, JButton> map; 

    ButtonMap(Class<E> buttonEnum){ 
     map = new EnumMap<>(buttonEnum); 
     for(E e : buttonEnum.getEnumConstants()){ 
      map.put(e, new JButton(e.toString())); 
     } 
    } 

    JButton get(E e){ 
     return map.get(e); 
    } 

} 

次のようになります。このマップを使用してビュー:

public class View { 

    private final ButtonMap<ViewButton> buttonMap = new ButtonMap<>(ViewButton.class); 
    public enum ViewButton{ 
     NEXT("Next"), 
     PREV("Prev"); 

     private final String name; 

     private ViewButton(String name){ 
      this.name = name; 
     } 

     @Override 
     public String toString(){ 
      return name; 
     } 
    } 

    public void setup() { 
     JPanel buttons = new JPanel(); 
     buttons.setLayout(new FlowLayout()); 
     buttons.add(buttonMap.get(ViewButton.PREV)); 
     buttons.add(buttonMap.get(ViewButton.NEXT)); 
    } 

    public void addActionListener(ViewButton button, ActionListener l){ 
     buttonMap.get(button).addActionListener(l); 
    } 

} // end view 

ボタンマップはプライベートフィールドで非表示になっています。ボタンの方法はaddActionListenerのみ公開されています。

関連する問題