首页 > 解决方案 > 完全透明的观察者

问题描述

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

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需要记住调用this.notifyObservers()adjustString方法。这没什么大不了的,但我想看看是否有办法完全隐藏这一点。

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

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接口的层)之间也不再统一了。

有没有简单的方法来拥有这个功能,但要public void adjustString(Set<String> strings)在课堂上保持签名MyLayer

标签: javaoopdesign-patternsobserver-patterntemplate-method-pattern

解决方案


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

    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();
   }

抽象类ObservableLayer更改为实现IObservableLayer而不是Layer直接实现。这个类仍然是公开的,以支持应用程序类定义可观察层的变体。

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

    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());

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


推荐阅读