完全透明的观察者
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();
}
}
我正在通过以下方式实现观察者模式:
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();
}
}