我应该使用监听器还是观察者?

Sim*_*onw 16 java swing arraylist listener observer-pattern

我的GUI中有一个下拉框,显示另一个类中ArrayList的内容.可以将新对象添加到GUI中其他位置的ArrayList,因此我需要知道它何时更新,因此我可以刷新下拉菜单.从我可以收集的内容来看,我的两个选项是扩展ArrayList类以允许我向其添加我自己的changeListener,或者使包含有问题的ArrayList的类扩展为observable.

哪个是更合适的解决方案?

Jar*_*red 11

这两个解决方案基本上是相同根设计模式的实现(由Gang of Four定义的"Observer"模式.)在前一种情况下,您将使ArrayList本身"可观察",在后者中您正在创建域使用数组列表"observable"的对象.

我倾向于做后者:使域对象可观察.这主要是因为您最终可能会有其他可能更改域对象的事情(应该更新GUI.)如果已经可以观察到,那么您已经设置好了.

请注意,您不必严格扩展java.util.Observable- 您可以在不执行此操作的情况下实现设计模式.


eri*_*son 9

ObservableJava中的实现很少使用,并且不能与Swing良好地交互.请EventListener改用.

特别是,在"GUI中其他地方"管理列表内容时,有没有理由不直接扩展AbstractListModel甚至DefaultListModel直接使用?然后你的组合框可以使用一个ComboBoxModel代理到同一个ListModel实例,添加自己的实现来跟踪选择状态.

我想到这样的事情(但我没有测试过):

final class MyComboBoxModel 
  extends AbstractListModel 
  implements ComboBoxModel 
{

  private final ListModel data;

  private volatile Object selection;

  MyComboBoxModel(ListModel data) { 
    /* 
     * Construct this object with a reference to your list, 
     * which contents are managed somewhere else in the UI.
     */
    this.data = data;
    data.addListDataListener(new ListDataListener() {
      public void contentsChanged(ListDataEvent evt) { 
        fireContentsChanged(this, evt.getIndex0(), evt.getIndex1()); 
      }
      public void intervalAdded(ListDataEvent evt) { 
        fireContentsChanged(this, evt.getIndex0(), evt.getIndex1()); 
      }
      public void intervalRemoved(ListDataEvent evt) { 
        fireContentsChanged(this, evt.getIndex0(), evt.getIndex1()); 
      }
    });
  }

  public void setSelectedItem(Object selection) { 
    this.selection = selection;
    fireContentsChanged(this, 0, data.getSize() - 1);
  }

  public Object getSelectedItem() { return selection; }

  public int getSize() { return data.getSize(); }

  public Object getElementAt(int idx) { return data.getElementAt(idx); }

}
Run Code Online (Sandbox Code Playgroud)