在ObserverPattern中,有一个Subject主题,多个Observer通过attach操作注册到Subject,是一对多的关系。
当Subject的状态改变时,通过notify机制通知所有Observer,通知方式通常是调用Observer的某个方法。
当Observer不再关注Subject的状态时,可以通过detach方法取消注册。
ObserverPattern的类图如下图所示:

ObserverPattern的时序图如下:

借用wiki上的代码:
class EventSource { // Subject接口
public interface Observer { // Observer接口,
void update(String event);
}
private final List<Observer> observers = new ArrayList<>(); // Subject维护一组Observer
private void notify(String event) { // notify操作不会直接更新Observer的状态,而是通知Observers,调用其update操作进行相应的更新,实现了Subject和Observer的解耦
observers.forEach(observer -> observer.update(event));
}
public void attach(Observer observer) { // 注册Observer
observers.add(observer);
}
public void detach(Observer observer) { // 取消Observer
observers.remove(observer);
}
public void scanSystemIn() { // scanner读取输入,引起状态改变,进而通知Observers
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
notify(line);
}
}
}
public class ObserverDemo {
public static void main(String[] args) {
sout("Enter Text: ");
EventSource eventSource = new EventSource; // 创建Subject
eventSource.attach(event -> { sout("Received response: " + event); }); // 匿名的Observer
eventSource.scanSystemIn();
}
}
从JDK1.0起,原生支持了ObserverPattern,位于java.util包中,其类图如下:

Observer接口比较简单,update方法接收被观察者Observable和参数Object:
public interface Observer {
void update(Observable o, Object arg);
}
Observable类使用一个Vector维护一组Observer,使用boolean变量changed标记状态是否发生变化,如果changed=false,notify方法不再通知到Observer。
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;
public Observable() { obs = new Vector<>(); }
// 添加和移除Observer
public synchronized void addObserver(Observer o) {
if (o == null) { throw new NPE(); }
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
// notify
public void notifyObservers() { notifyObservers(null); }
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed) { return; }
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length - 1; i >= 0; i--) {
((Observer) arrLocal[i]).update(this, arg);
}
}
// 清空Observer
public synchronized void deleteObservers() { obs.removeAllElements(); }
// getter/setter
protected synchronized void setChanged() { changed = true; }
protected synchronized void clearChanged() { changed = false; }
public synchronized boolean hasChanged() { return changed; }
public synchronized int countObservers() { return obs.size(); }
}
使用jdk原生接口实现一个ObserverPattern模式的例子:
首先是Observable:
public class DataStore extends Observable {
private String data; // data即是Observable的状态
public String getData() { return data; }
public void setData(String data) {
this.data = data;
setChanged(); // 父类Observable定义的方法,标记changed,但不notify
}
}
然后是Observer:
public class Screen implements Observer {
@Override
void update(Observable o, Object arg) {
// Observer的响应操作
}
}
业务类:
public class ObserverDemo {
public static void main(String[] args) {
Screen screen = new Screen(); // 创建一个Observer
DataStore dataStore = new DataStore(); // 创建一个Observable
dataStore.addObserver(screen); // 注册Observer
dataStore.setData(data); // 更新Observable自身的状态
dataStore.notifyObservers(); // 通知Observer
}
}
参考:
- https://dzone.com/articles/design-patterns-uncovered
- https://en.wikipedia.org/wiki/Observer_pattern
1551

被折叠的 条评论
为什么被折叠?



