先看定义 ,观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
应用: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方法。