先看定义 ,观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
应用:j2se的AWT事件处理机制是基于观察者模式的,在Spring中的应用是事件传播机制。
从定义中可以看出,所谓观察者模式,就必须有观察者和被观察者,当被观察者状态发生改变时(比如属性值改变等),所有观察者都得到通知并更新。
这就非常类似事件处理机制,事件处理机制有事件和Listener,事件就像被观察者,当事件被触发的时,就相当于观察者状态改变,这是就自动触动Listener(被观察者)。
先看java.util.Observe接口(观察者)
public interface Observer { /** * This method is called whenever the observed object is changed. An * application calls an <tt>Observable</tt> object's * <code>notifyObservers</code> method to have all the object's * observers notified of the change. * * @param o the observable object. * @param arg an argument passed to the <code>notifyObservers</code> * method. */ void update(Observable o, Object arg); } }
先不解释,看被观察者java.util.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); } }
ok,这里有个addObserve(Observe o)的方法,也就是说在这个方法里给被观察者添加观察者,当被观察者状态变化时,将调用notifyObservers(Object arg)方法,传的这个参数将传给观察者,以供观察者使用(改变属性或者做相应的事件处理)(所以观察者里有个UPDATE(Observable o,Object arg))。
观察者必须实现Observe 接口,被观察者必须继承Observable
下面来一个实例 定义4个观察者,分别观察名字和价格属性
public class PriceObserver1 implements Observer{ public void update(Observable o, Object arg) { System.out.println("PriceObserver1 价格改变为:"+arg); } } public class PriceObserver2 implements Observer{ public void update(Observable o, Object arg) { System.out.println("PriceObserver2价格改变为:"+arg); } } public class NameObserver1 implements Observer{ public void update(Observable o, Object arg) { System.out.println("NameObserver1 价格改变为:"+arg); } } public class NameObserver2 implements Observer{ public void update(Observable o, Object arg) { System.out.println("NameObserver2 价格改变为:"+arg); } }
再来一个被观察者
public class Product extends Observable{ public String name; public int price; public Product(){} public Product(String name,int price){ this.name=name; this.price=price; } public String getName(){ return this.name; } public void setName(String name){ this.name=name; // 一旦改变name属性,就通知观察者 notifyObservers(name); } public int getPrice(){ return this.price; } public void setPrice(int price){ this.price=price; // 一旦改变name属性,就通知观察者 notifyObservers(price); } public static void main(String [] args) { //创建一个被观察者 Product product = new Product ("aaa",1); System.out.println("product name="+product.getName()+";price="+product.getPrice()); //创建四个观察者 Observer priceObserver1= new PriceObserver1(); Observer priceObserver2= new PriceObserver2(); Observer nameObserver1= new NameObserver1(); Observer nameObserver2= new NameObserver2(); //把4个观察者加到被观察者列表中 product.addObserver(priceObserver1); product.addObserver(priceObserver2); product.addObserver(nameObserver1); product.addObserver(nameObserver2); product.setName("bbb"); product.setPrice(2); } }
这个例子很明显 被观察者的name或者price属性改变后,将通知观察者update(Observe o,object obj)做出相应的响应。究其原因,是改变属性的时候,调用
notifyObservers
方法,这个方法是在被观察者的父类里定义的,父类里这方法又调用了观察者接口的update方法,这也就是观察者模式内部的玄机了,我说观察者咋就可以观察到被观察对象的改变呢,原来我们实现了观察者接口的update方法。