观察者模式简介:
定义:定义对象间的一对多的依赖关系,当一个对象的状态改变时,所有依赖于它的对象都得到通知并被自动更新。
使用例子:
网上商店中的商品在名称、价格发生变化时,必须自动通知会员,Java的API为我们提供了Observer接口和Observable类来实现观察者模式。
Observable(可观察者)类允许在自身发生改变时,通知其它对象(实现接口Observer,观察者)。
使用java.util.Observer接口和java.util.Observable类实现观察者模式:
观察者实现Observer接口,并重写其中的update方法,供被观察者状态改变时调用。
被观察者继承Observable类,在Observable类中有增加,删除观察者类的方法,还有通知所有观察者都update的方法。状态改变时,先setChanged,再notifyObservers。
Observer观察者接口源码:
package java.util; public interface Observer { /** * 当被观察的对象发生变化时,这个方法会被调用。 */ void update(Observable o, Object arg); }
被观察者Observable类源码:
package java.util; public class Observable { private boolean changed = false; private Vector obs; /** 用0个观察者构造一个被观察者。**/ public Observable() { obs = new Vector(); } /** * 将一个观察者加到观察者列表上面。 */ public synchronized void addObserver(Observer o) { if (!obs.contains(o)) { obs.addElement(o); } } /** * 将一个观察者对象从观察者列表上删除。 */ public synchronized void deleteObserver(Observer o) { obs.removeElement(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 = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); } /** * 将观察者列表清空 */ public synchronized void deleteObservers() { obs.removeAllElements(); } /** * 将“已变化”设为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 obs.size(); } }
下面是一个被观察者(产品类):
import java.util.*; public class product extends Observable{ private String name;////产品名 private float price;////价格 public String getName(){ return name;} public void setName(String name){ this.name=name; ////设置变化点 setChanged(); notifyObservers(name);////通知观察者 } public float getPrice(){ return price;} public void setPrice(float price){ this.price=price; ////设置变化点 setChanged(); notifyObservers(new Float(price)); } ////以下可以是数据库更新 插入命令. public void saveToDb(){ System.out.println("saveToDb"); } }
下面是两个观察者:
import java.util.*; public class NameObserver implements Observer{ private String name=null; public void update(Observable obj,Object arg){ if (arg instanceof String){ name=(String)arg; ////产品名称改变值在name中 System.out.println("NameObserver :name changet to "+name); } } } import java.util.*; public class PriceObserver implements Observer{ private float price=0; public void update(Observable obj,Object arg){ if (arg instanceof Float){ price=((Float)arg).floatValue(); System.out.println("PriceObserver :price changet to "+price); } } }
下面是测试类:
public class Test { public static void main(String args[]){ Product product=new Product(); Observer nameobs=new NameObserver(); Observer priceobs=new PriceObserver(); ////加入观察者 product.addObserver(nameobs); product.addObserver(priceobs); product.setName("applet"); product.setPrice(9.22f); } }
运行结果:
C:\java>java Test
NameObserver :name changet to applet
PriceObserver :price changet to 9.22