【Practical API Design学习笔记】不要滥用JavaBeans监听机制

    JavaBeans机制没有大部分人想得那么简单,它不仅仅包括setter和getter。

    例如:有一个用来在编辑器中将特别信息高亮显示的API。它允许其他模块将各自实现的HighlightsContainers注册到指定位置。这些注册的内容可以用来计算一个编辑器中的某部分文字内容的高亮区域,而且根据高亮区域的改变,这些内容会发出消息加以通知。这种功能的设计完全可以用JavaBeans的设计模式。

【Practical API Design学习笔记】不要滥用JavaBeans监听机制

    以上代码的问题是removeHighlightsChangeListener方法永远不会被调用。实现HighlightsContainer的类智能被回收。

    一种解决方案是写一个AbstractHighlightsContainer的基类,它实现HighlightsContainer接口,然后实现了支持添加和删除Listener的方法,并将这两个方法声明为final,两外再写一个声明为protected final void fireHightlightsChanged()的方法。这样,开发人员只要继承这个基类就可以了。但是为什么要给用户基类?这样会增加用户学习成本,这不是个好主意。

    另一种解决方案是支持有限的监听器,否则会抛出异常。

    实现类如下:

final class MyHighlightsContainer implements HighlightsContainer {
  private HighlightsChangeListener listener;
  public synchronized void addHighlightsChangeListener(
    HighlightsChangeListener l) throws TooManyListenersException {
    if (listener != null) throw new TooManyListenersException();
    listener = l;
  }
  public synchronized void removeHighlightsChangeListener(
    HighlightsChangeListener l
  ) {
    if (listener == l) listener = null;
  }
  public HighlightsSequence getHighlights(int start, int end) {
    return null; // implement
  }
}
    但是以上代码中也有不会被使用的无用代码,就是removeHighlightsChangeListener方法。

    在NetBeans在制定API设计规范时,这种情况不适合使用JavaBeans的方案。而是建议使用“回调”方案。

public interface HighlightsContainer {
  public void initialize(Callback callback);
  public HighlightsSequence getHighlights(int start, int end);
  public static final class Callback {
    Callback() { /* only for the infastructure */ }
    public final void highlightsChanged() {
      // refresh everything
    }
  }
}
    当然,在HighlightsContainer这个类的设计时,因为不止一个Listener来监听相应容器事件,于是采用的是JavaBeans的设计模式。但在NetBeans平台中,还有一些其他的API,回调的设计方式会比JavaBeans设计模式更合适一些。

你可能感兴趣的:(api)