简单地说观察者模式定义了一个一对多的依赖关系让一个或多个观察者对象监察一个主题对象这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象使这些观察者对象能够自动更新 观察者模式的结构 观察者(Observer)模式是对象的行为型模式又叫做发表订阅(Publish/Subscribe)模式模型视图(Model/View)模式源收听者(Source/Listener)模式或从属者(Dependents)模式 本模式的类图结构如下 图观察者模式的静态结构可从类图中看清楚 在观察者模式里有如下的角色 抽象主题(Subject)角色主题角色把所有的观察者对象的引用保存在一个列表里每个主题都可以有任何数量的观察者主题提供一个接口可以加上或撤销观察者对象主题角色又叫做抽象被观察者(Observable)角色 图抽象主题角色有时又叫做抽象被观察者角色可以用一个抽象类或者一个接口实现在具体的情况下也不排除使用具体类实现 抽象观察者(Observer)角色为所有的具体观察者定义一个接口在得到通知时更新自己 图抽象观察者角色可以用一个抽象类或者一个接口实现在具体的情况下也不排除使用具体类实现 具体主题(ConcreteSubject)角色保存对具体观察者对象有用的内部状态在这种内部状态改变时给其观察者发出一个通知具体主题角色又叫作具体被观察者角色 图具体主题角色通常用一个具体子类实现 .具体观察者(ConcreteObserver)角色保存一个指向具体主题对象的引用和一个与主题的状态相符的状态具体观察者角色实现抽象观察者角色所要求的更新自己的接口以便使本身的状态与主题的状态自恰 图具体观察者角色通常用一个具体子类实现 下面给出一个示意性实现的Java代码首先在这个示意性的实现里用一个Java接口实现抽象主题角色这就是下面的Subject接口 public interface Subject { public void attach(Observer observer); public void detach(Observer observer); void notifyObservers(); } 代码清单Subject接口的源代码 这个抽象主题接口规定出三个子类必须实现的操作即 attach() 用来增加一个观察者对象detach() 用来删除一个观察者对象和notifyObservers() 用来通知各个观察者刷新它们自己抽象主题角色实际上要求子类保持一个以所有的观察者对象为元素的列表 具体主题则是实现了抽象主题Subject接口的一个具体类它给出了以上的三个操作的具体实现从下面的源代码可以看出这里给出的Java实现使用了一个Java向量来保存所有的观察者对象而 attach() 和 detach() 操作则是对此向量的元素增减操作 import javautilVector; import javautilEnumeration; public class ConcreteSubject implements Subject public void attach(Observer observer) { observersVectoraddElement(observer); } public void detach(Observer observer) { observersVectorremoveElement(observer); } public void notifyObservers() { Enumeration enumeration = observers(); while (enumerationhasMoreElements()) { ((Observer)enumerationnextElement())update(); } } public Enumeration observers() { return ((Vector) observersVectorclone())elements(); } private Vector observersVector = new javautilVector(); } 代码清单ConcreteSubject类的源代码 抽象观察者角色的实现实际上是最为简单的一个它是一个Java接口只声明了一个方法即update()这个方法被子类实现后一被调用便刷新自己 public interface Observer { void update(); } 代码清单Observer接口的源代码 具体观察者角色的实现其实只涉及update()方法的实现这个方法怎么实现与应用密切相关因此本类只给出一个框架 public class ConcreteObserver implements Observer { public void update() { // Write your code here } } 代码清单ConcreteObserver类的源代码 虽然观察者模式的实现方法可以有设计师自己确定但是因为从AWT开始视窗系统的事件模型采用观察者模式因此观察者模式在Java语言里的地位较为重要正因为这个原因Java语言给出了它自己对观察者模式的支持因此本文建议读者在自己的系统中应用观察者模式时不妨利用Java语言所提供的支持 Java语言提供的对观察者模式的支持 在Java语言的javautil库里面提供了一个Observable类以及一个Observer接口构成Java语言对观察者模式的支持 Observer接口 这个接口只定义了一个方法update()当被观察者对象的状态发生变化时这个方法就会被调用这个方法的实现应当调用每一个被观察者对象的notifyObservers()方法从而通知所有的观察对象 图javautil提供的Observer接口的类图 package javautil; public interface Observer { /** * 当被观察的对象发生变化时这个方法会被调用 */ void update(Observable o Object arg); } 代码清单javautilObserver接口的源代码 Observable类 被观察者类都是javautilObservable类的子类javautilObservable提供公开的方法支持观察者对象这些方法中有两个对Observable的子类非常重要一个是setChanged()另一个是notifyObservers()第一个方法setChanged()被调用之后会设置一个内部标记变量代表被观察者对象的状态发生了变化第二个是notifyObservers()这个方法被调用时会调用所有登记过的观察者对象的update()方法使这些观察者对象可以更新自己 javautilObservable类还有其它的一些重要的方法比如观察者对象可以调用javautilObservable类的addObserver()方法将对象一个一个加入到一个列表上当有变化时这个列表可以告诉notifyObservers()方法那些观察者对象需要通知由于这个列表是私有的因此javautilObservable的子对象并不知道观察者对象一直在观察着它们 图Java语言提供的被观察者的类图 被观察者类Observable的源代码 package javautil; public class Observable { private boolean changed = false; private Vector obs; /** 用个观察者构造一个被观察者**/ public Observable() { obs = new Vector(); } /** * 将一个观察者加到观察者列表上面 */ public synchronized void addObserver(Observer o) { if (!ntains(o)) { obsaddElement(o); } } /** * 将一个观察者对象从观察者列表上删除 */ public synchronized void deleteObserver(Observer o) { obsremoveElement(o); } /** * 相当于 notifyObservers(null) */ public void notifyObservers() { notifyObservers(null); } /** * 如果本对象有变化(那时hasChanged 方法会返回true) * 调用本方法通知所有登记在案的观察者即调用它们的update()方法 * 传入this和arg作为参量 */ public void notifyObservers(Object arg) { /** * 临时存放当前的观察者的状态参见备忘录模式 */ Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obstoArray(); clearChanged(); } for (int i = arrLocallength; i>=; i) ((Observer)arrLocal[i])update(this arg); } /** * 将观察者列表清空 */ public synchronized void deleteObservers() { obsremoveAllElements(); } /** * 将已变化设为true */ protected synchronized void setChanged() { changed = true; } /** * 将已变化重置为false */ protected synchronized void clearChanged() { changed = false; } /** * 探测本对象是否已变化 */ public synchronized boolean hasChanged() { return changed; } /** * 返还被观察对象(即此对象)的观察者总数 */ public synchronized int countObservers() { return obssize(); } } 代码清单 |