观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态上发生变化时,会通知所有观察者对象。
模式组成
Subject,抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题角色又叫做抽象被观察者(Observable)角色
Observer,抽象观察者角色:在得到主题的通知时进行操作
ConcreteSubject,具体主题角色:在具体主题内部状态改变时,给所有登记过的观察者发出通知
ConcreteObserver,具体观察者角色:实现抽象观察者角色所要求的更新接口,如果需要,具体观察者角色可以保存一个指向具体主题角色的引用
/* * 抽象观察者角色 */ public interface Watcher { public void update(String str); } /* * 抽象主题角色 * 增加、删除、通知观察者 */ public interface Watched { public void addWatcher(Watcher watcher); public void removeWatcher(Watcher watcher); public void notifyWatchers(String str); }
/* * 具体被观察者 */ public class WatchedSubject implements Watched { // 存放观察者 private List<Watcher> list = new ArrayList<Watcher>(); @Override public void addWatcher(Watcher watcher) { list.add(watcher); } @Override public void removeWatcher(Watcher watcher) { list.remove(watcher); } @Override public void notifyWatchers(String str) { for (Watcher watcher : list) { watcher.update(str); } } } /* * 具体的观察者 */ public class WatcherImpl implements Watcher{ @Override public void update(String str) { // ... } }
示例
public static void main(String[] args) { // 创建观察者对象 Watcher watcher = new WatcherImpl(); // 创建主题对象 Watched watched = new WatchedSubject(); // 观察者观察主题对象 watched.addWatcher(watcher); // 通知所有观察者 watched.notifyWatchers("123"); }
Java提供的接口支持
Observer接口,观察者动作
public interface Observer { void update(Observable o, Object arg); }
Observable类,被观察者类
public class Observable { private boolean changed = false; private Vector obs; public Observable() { obs = new Vector(); } public synchronized void addObserver(Observer o) { if (o == null) throw new NullPointerException(); if (!obs.contains(o)) { obs.addElement(o); } } public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } 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); } public synchronized void deleteObservers() { obs.removeAllElements(); } 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(); } }