完全透明的观察者

Observer with full transparency

我正在通过以下方式实现观察者模式:

interface Layer{
    void adjustString(Set<String> strings);
}

interface NotifiableLayer extends Layer{
    void layerAdjusted(Layer layer);
}

abstract class ObservableLayer implements Layer{
    Set<NotifiableLayer> observers = new HashSet<>();

    void addObserver(NotifiableLayer layer){
        observers.add(layer);
    }
    void removeObserver(NotifiableLayer layer){
        observers.remove(layer);
    }

    void notifyObservers(){
        observers.forEach(l -> l.layerAdjusted(this));
    }
}

class MyLayer extends ObservableLayer{
    @Override
    public void adjustString(Set<String> strings) {
        this.notifyObservers(); //can this be auto?
    }
}

这当然有效,但是实施 ObservableLayer 的人需要记住在 adjustString 方法中调用 this.notifyObservers()。这没什么大不了的,但我想看看是否有办法完全隐藏它。

到目前为止,我只有这个想法(使用模板方法):

abstract class ObservableLayer implements Layer{
    //...methods removed for simplicity

    @Override
    public void adjustString(Set<String> strings) {
        this.doAdjustString(strings);
        this.notifyObservers(); //<---- here is auto
    }

    abstract void doAdjustString(Set<String> strings);
}

class MyLayer extends ObservableLayer{
    @Override
    public void doAdjustString(Set<String> strings) {
        //now notification is in base adjustString
    }
}

但是这里我不喜欢把方法名改成doAdjustString,并且在其他层实现之间不再统一(直接实现Layer接口的层)。

有什么简单的方法可以实现此功能,但要在 MyLayer class 中保留 public void adjustString(Set<String> strings) 签名?

一种方法是使用一个包含 ObservableLayer 实例并委托给它的 Decorator 实例。

    final class LayerDecorator implements Layer {
      final private ObservableLayer delegate;

      public LayerDecorator(ObservableLayer delegate) {
        this.delegate = delegate;
      }

      @Override
      public void adjustString(Set<String> strings) {
        delegate.adjustString(strings);
        delegate.notifyObservers();
      }
    }

这假定调用代码正在使用对 Layer 的引用而不是 ObservableLayer

如果调用代码必须使用对 ObservableLayer 的引用才能工作,那么也许最好将 ObservableLayer 重构为一个具有注册侦听器、删除它们并通知它们的方法的接口。此接口还扩展了 Layer 接口。

   interface IObservableLayer extends Layer {
     void addObserver(NotifiableLayer layer);
     void removeObserver(NotifiableLayer layer);
     void notifyObservers();
   }

抽象 class ObservableLayer 更改为实现 IObservableLayer 而不是直接实现 Layer。 class 仍然 public 以支持应用程序 classes 来定义可观察层的变体。

接下来可以定义可观察层的内部装饰器,如下所示。

    final class ObservableLayerDecorator implements IObservableLayer {
      final private ObservableLayer delegate;

      public ObservableLayerDecorator(ObservableLayer delegate) {
        this.delegate = delegate;
      }

      @Override
      public void addObserver(NotifiableLayer layer) {
        delegate.addObserver(layer);
      }

      @Override
      public void removeObserver(NotifiableLayer layer) {
        delegate.removeObserver(layer);
      }

      @Override
      public void notifyObservers() {
        delegate.notifyObservers();
      }

      @Override
      public void adjustString(Set<String> strings) {
        delegate.adjustString(strings);
        this.notifyObservers();
      }
    }

请注意在这种情况下通知是如何完成的。

现在 IObservableLayer 的实例可以创建为

    IObservableLayer observableLayer = new ObservableLayerDecorator(new MyClass());

工厂方法在这里会很有帮助,因为它们可以被定义为处理各种 application-level 可观察层 classes 的创建,以便可以一致地创建实例 return IObservableLayer这是装饰。这将使开发人员无需了解如何使用装饰器,并允许装饰器成为内部实用程序。

另一种方法是面向方面的编程。

以下示例使用 AspectJ 拦截 class 扩展 Observable 上的任何 public 方法执行,并在同一对象上调用 notifyObservers()

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class EventAspect {
    @AfterReturning("execution(public * Observable.*(..)) && target(observable)")
    public void notifyObservers(Observable observable) {
        observable.notifyObservers();
    }
}