Mor*_*itz 0 java design-patterns interface observer-pattern
题
我无法理解“可重用面向对象软件的元素”中观察者模式的以下 UML 图。谁能解释我为什么我的 Java 实现是错误的,我必须改变什么才能正确实现它?
UML-图
尝试(但错误)实施
public interface Subject {
public static final List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer o);
public void detach(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update();
}
public class ConcreteSubject implements Subject {
private String subjectState;
@Override
public void attach(Observer o) {
observers.add(o);
}
@Override
public void detach(Observer o) {
observers.remove(o);
}
@Override
public void notifyObservers() {
for (Observer o : observers) {
o.update();
}
}
public String getState() {
return subjectState;
}
public void setState() {
subjectState += "x";
}
}
public class ConcreteObserver implements Observer {
private ConcreteSubject subject;
public String observerState;
@Override
public void update() {
observerState = subject.getState();
}
}
Run Code Online (Sandbox Code Playgroud)
一个问题是您有一个静态的观察者列表,Subject因此所有主题都共享相同的观察者。但是,该模式要求每个单独的主题都有自己的观察者,因此将列表放入ConcreteSubject并使其成为实例字段。
另一个问题是您ConcreteObserver有一个 type 字段ConcreteSubject。但是,它应该不知道Subjectso 的具体实现,因此该字段应该只有 type Subject。
编辑:实际上,UML 图要求具体的观察者了解具体的主题,以便能够调用,getState()因此上面的段落在您的情况下不正确 - 这应该不是问题。
但是,实际上我实际上会有另一个接口来扩展Subject和隐藏ConcreteSubject观察者的实现。
编辑2:
正如所建议的那样,您还可以使用抽象类来处理主题的观察者。这可能是一个阶级之间Subject和ConcreteSubject甚至Subject本身,而是因为Java不支持多重继承我会经常使用一些其他的办法,使Subject只是一个接口。
最简单的实现是ConcreteSubject维护观察者列表,但在现实世界的应用程序中,您不希望开发人员这样做或依赖他们正确实现它。
相反,您可以使用一个中央注册表来维护每个主题的观察者列表,并且主题使用它来通知其观察者。许多依赖注入框架以这种方式运行,即每当“主题”发生变化时,它们都会通知其观察者该事件。