1、java.util.Observable类源码:
package java.util; /** * 一个observable对象可以有一个或多个观察者,观察者是实现了Observer接口的任意对象。 * 一个observable对象实例改变后,调用notifyObservers方法就可以调用观察者的update方法来通知观察者:该observable实例改变了 * @author Chris Warth * @version 1.38, 01/12/04 * @since JDK1.0 */ public class Observable { //此对象状态标示 改变为true 未改变为false 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); } /** * 调用notifyObservers(Object arg),参数为null */ public void notifyObservers() { notifyObservers(null); } /** * 如果此对象状态已改变,则通知所有观察者,最后调用clearChanged方法还原状态(未改变) * arg:任意对象 */ public void notifyObservers(Object arg) { Object[] arrLocal; /** * 这里加synchronized关键字声明对当前对象加锁,当调用该方法时,当前对象不能再执行其他synchronized方法 * 避免以下两种情况: * 1、通知的同时如果有新的观察者加入进来,这样有可能就会通知不到 * 2、有可能通知的同时有观察者离开了,会导致错误的通知到已经不是观察者的对象 */ synchronized (this) { //如果changed为false表示此对象未改变,则return,如果为true,表示已改变,继续执行下面语句 if (!changed) return; //将观察者集合转换成数组 arrLocal = obs.toArray(); //清除当前对象已改变状态,changed被重新赋值为false clearChanged(); } /** * 循环遍历数组,取出观察者进行update()操作 * update是观察者接口Observer中需要实现的一个方法,里面 * 可以写上观察者接收到通知后所做出的逻辑处理 * 发送通知的顺序默认是按照他们添加顺序来的 */ for (int i = arrLocal.length - 1; i >= 0; i--) ((Observer) arrLocal[i]).update(this, arg); } /** * 清除观察者列表,使此对象不再有任何观察者 */ public synchronized void deleteObservers() { obs.removeAllElements(); } /** * 标记此 Observable 对象为已改变的对象,changed被赋值为true */ protected synchronized void setChanged() { changed = true; } /** * 清除已改变状态,changed被重新赋值为false */ protected synchronized void clearChanged() { changed = false; } /** * 查询对象状态是否改变,返回值为changed */ public synchronized boolean hasChanged() { return changed; } /** * 返回观察者数目 */ public synchronized int countObservers() { return obs.size(); } }
2、观察者1(中国记者):
package service; import java.util.Observable; import java.util.Observer; /** * 功能:观察者 * 类名:ChineseObserver * 作者:smile * 时间:Nov 13, 2012:10:32:49 PM */ public class ChineseObserver implements Observer { public void update(Observable o, Object arg) { System.out.println("听"+o.getClass().getName()+"说"+arg+",尼玛,房价又涨了"); } }
3、观察者2(美国记者):
package service; import java.util.Observable; import java.util.Observer; /** * 功能:观察者 * 类名:UsaObserver * 作者:smile * 时间:Nov 13, 2012:10:33:49 PM */ public class UsaObserver implements Observer { public void update(Observable o, Object arg) { System.out.println("听"+o.getClass().getName()+"说"+arg+",Fuck,price of the house has risen again"); } }
4、被观察的对象(外交部发言人):
package service; import java.util.Observable; /** * 功能:被观察者(外交官) * 类名:Diplomat * 作者:smile * 时间:Nov 13, 2012:10:30:26 PM */ public class Diplomat extends Observable { /** * 执行开记者发布会操作,通知所有观察者 */ public void meet(){ //改变状态 super.setChanged(); //通知所有观察者 notifyObservers("房价要继续涨起。。。"); } }
5、测试类:
package service; public class Test { public static void main(String[] args) { //实例化一个中国观察者 ChineseObserver chinese = new ChineseObserver(); //实例化一个美国观察者 UsaObserver usa = new UsaObserver(); Diplomat target = new Diplomat (); //将中国观察者加入到观察者集合中 target.addObserver(chinese); //将美国观察者加入到观察者集合中 target.addObserver(usa); //外交官开记者会,状态改变,通知观察者 target.meet(); } }
6、打印信息:
听service.Diplomat 说房价要继续涨起...,Fuck,price of the house has risen again 听service.Diplomat 说房价要继续涨起...,尼玛,房价又涨了
7、观察者与Spring,修改Diplomat 类:
package service; import java.util.Observable; import java.util.Observer; import java.util.Vector; /** * 功能:被观察者(外交官) * 类名:Diplomat * 作者:smile * 时间:Nov 13, 2012:10:30:26 PM */ public class Diplomat extends Observable { /** * 执行某个操作会更改状态,通知所有观察者 */ public void meet(){ //改变状态 super.setChanged(); //通知所有观察者 notifyObservers("房价要继续涨起..."); } /** * 添加一组观察者 */ public void addObservers(Observer[] obj){ //先这么简单写了 for(Observer o:obj){ addObserver(o); } } }
8、Spring XML配置文件:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 中国观察者Bean --> <bean id="chineseObserver" class="service.ChineseObserver" /> <!-- 美国观察者Bean --> <bean id="usaObserver" class="service.UsaObserver" /> <!-- 被观察的对象Bean --> <bean id="dplomat " class="service.Diplomat" /> <!-- 该Bean实例化时 以上两个观察者就已经被注入到被观察者中去了 --> <bean id="autoAddObserver" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <!-- targetObject确定目标Bean,指定调用哪个Bean --> <property name="targetObject"><ref local="dplomat"/></property> <!-- targetMethod确定目标方法,指定调用目标Bean的哪个方法 addObservers()方法添加一组观察者 --> <property name="targetMethod"><value>addObservers</value></property> <!-- 确定调用目标方法的参数 --> <property name="arguments"> <list> <ref bean="usaObserver"/> <ref bean="chineseObserver"/> </list> </property> </bean> </beans>
9、测试类:
package service; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class SpringTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean.xml"); //获取被观察对象 Diplomat target = (Diplomat) context.getBean("dplomat"); //外交官开记者招待会,状态改变,通知观察者 target.meet(); } }
10、打印信息:
2012-11-13 15:30:07 org.springframework.context.support.AbstractApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@c1b531: startup date [Tue Nov 13 15:30:07 GMT 2012]; root of context hierarchy 2012-11-13 15:30:07 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [bean.xml] 2012-11-13 15:30:07 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons 信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1630ab9: defining beans [chineseObserver,usaObserver,target,autoAddObserver]; root of factory hierarchy 听service.TargetObject说房价要继续涨起...,尼玛,房价又涨了 听service.TargetObject说房价要继续涨起...,Fuck,price of the house has risen again
11、小结:
1)、observer模式定义对象间的一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。 2)、应用场景:一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。