【问题标题】:Concise way to expose View's JButtons objects to Presenter将 View 的 JButtons 对象公开给 Presenter 的简洁方法
【发布时间】:2017-02-24 20:06:56
【问题描述】:

我正在使用 MVP 设计模式用 Java 编写一个 GUI 应用程序。 JButton 对象属于 View 类,ActionListener 对象属于 Presenter。我正在寻找一种简洁的方法来允许演示者将ActionListeners 添加到视图的JButtons 中,而无需(1)制作按钮public 和(2)而无需向视图添加一堆方法看起来像

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 允许演示者按名称引用它们(这允许我的 IDE 使用代码完成);但是,因为它们是WrappedJButton 对象,Presenter 唯一能做的就是添加一个 ActionListener。视图可以通过私有b 字段抓住“真实”按钮来“完全”访问对象。

问题:

  1. 是否有更好/更清洁的解决方案?也许是什么 将消除访问视图中的b 字段的需要吗?
  2. 有没有办法概括这个解决方案,所以我不必 将WrappedJButton 剪切并粘贴到我编写的每个视图类中?我 尝试将WrappedJButton 移动到界面中(查看 工具);但是,当我这样做时,View 不再有权访问 私人b 字段。

【问题讨论】:

    标签: java private mvp inner-classes code-completion


    【解决方案1】:

    我认为可以通过在包级别公开包装按钮来避免复制粘贴 WrapperJButton 类(假设 Presenter 位于不同的包中):

    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 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-06
      • 1970-01-01
      • 2020-09-24
      • 1970-01-01
      • 2023-01-09
      • 2017-10-04
      相关资源
      最近更新 更多