首先还是先来observer模式的uml图
Suject实际是被订阅的消息主题,比如报社,中国移动的天气预报套餐,。。。在Suject中保存了所有订阅者的引用,以便在通知订阅者时使用
Observer就是订阅者了,相当于就是订阅报纸的人了
在JDK中java.util.Observerable实现了Suject的功能,内部是通过线程安全的Vector保存所有订阅者的引用,在发送订阅消息是需通过setChanged();修改其状态值才能对订阅者发送消息,发送消息的顺序是先订阅后发送的顺序,这点需要注意。
java.util.Observer是一个接口,其中定义了update(Observerable o,Object arg)方法,第一个参数是被订阅者,可以让观察者知道是哪一个主题发送的消息,第二个参数是具体订阅的消息
在java awt的事件监听就是使用的观察者模式,需要对一个组件进行监听使用setXXlistenner进行监听
下面介绍一个简单的例子
房屋中介提供房屋出售的信息和房屋出租的信息,那么就可以让房屋中介继承Observerable
有的买房者对房屋中介的房屋出售价格感兴趣,有的对所有信息感兴趣,他可以对自己感兴趣的信息进行订阅,买房者实现Observer接口
一个房屋中介的简单代码
package com.akwolf.observer;
import java.util.Observable;
/**
* 房屋中介提供房屋价格变化的信息,也包括房屋出租等信息 在Observer中保存了Observer的应用使用vector实现
*
* @author zhanghua
*
*/
public class HouseAgency extends Observable {
/** 房屋中介所能提供的信息 */
private HouseAgencyInfo agencyInfo;
public HouseAgency() {
agencyInfo = new HouseAgencyInfo();
}
public void notifyAllObservers(HouseAgencyInfo oldInfo, HouseAgencyInfo newInfo) {
//System.out.println(oldInfo+"-----"+newInfo);
// 这里可以控制房屋中介不用太敏感,当房屋出售价格的变动大于100时通知观察者
if (Math.abs(newInfo.getHousePrice() - oldInfo.getHousePrice()) > 100) {
// 设置为通知状态,不设置的话观察者无法获取信息
setChanged();
notifyObservers(newInfo);
}
}
public HouseAgencyInfo getAgencyInfo() {
return agencyInfo;
}
public void setAgencyInfo(HouseAgencyInfo agencyInfo) {
// 保存价格变动前的信息
HouseAgencyInfo oldInfo = this.agencyInfo;
this.agencyInfo = agencyInfo;
notifyAllObservers(oldInfo, agencyInfo);
}
}
几个订阅者的代码,只列出一个观察者的代码
package com.akwolf.observer;
import java.util.Observable;
import java.util.Observer;
public class Jack implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof HouseAgency) {
// Jack只对房屋出售价格感兴趣,所以他可以使用“拉”的方式从房屋中介获得信息
HouseAgency agency = (HouseAgency) o;
System.out.println("Jack收到的消息--"+agency.getAgencyInfo().getHousePrice());
}
}
}
写一个测试类对房屋信息和观察者进行测试
package com.akwolf.observer;
public class MainTest {
public static void main(String[] args) {
//创建被观察者实例
HouseAgency houseAgency = new HouseAgency() ;
//创建观察者实例
Jack jack = new Jack() ;
Tom tom = new Tom() ;
Jim jim = new Jim() ;
//观察者订阅主题关注自己所关注的信息
houseAgency.addObserver(jack) ;
houseAgency.addObserver(tom) ;
houseAgency.addObserver(jim) ;
//ok,现在房屋的价格发生变化了
HouseAgencyInfo agencyInfo = new HouseAgencyInfo(6000,800) ;
houseAgency.setAgencyInfo(agencyInfo) ;
System.out.println("-------1-------");
//房屋的变化信息小于100,所有订阅者不会收到消息
agencyInfo = new HouseAgencyInfo(6010,800) ;
houseAgency.setAgencyInfo(agencyInfo) ;
System.out.println("-------2-------");
//房屋的信息大于100
agencyInfo = new HouseAgencyInfo(7000,850) ;
houseAgency.setAgencyInfo(agencyInfo) ;
System.out.println("----3-----");
//Tom已经买房子了,所以不再对房屋中介的信息感兴趣,他退订了信息
houseAgency.deleteObserver(tom) ;
//房屋价格再次变化
agencyInfo = new HouseAgencyInfo(8000,100) ;
houseAgency.setAgencyInfo(agencyInfo) ;
}
}
测试结果
ok到这里观察者模式的小例子介绍完毕,有不明白的童鞋和认为我讲的不对的童鞋欢迎拍砖,一起讨论进步!!
附上源码下载地址:http://download.youkuaiyun.com/source/3574114