Observer是在JDK中使用十分广泛的,SWING和MVC等等都大量用到了。
首先看个例子:
对于一个WeatherData类,记录了Weather的变化,实时数据,现在需要提供一些平台对于这些数据进行实时的更新公布
public class WeatherData{
private float temperture
private float wet
public getXX(){
}
public changeEvent(){
//当数据变化时,调用
}
}
观察者模式,包含两类实体,一是Subject,二是Observer,两者是一对多的关系,
同时他们之间实现的是松耦合。
什么是松耦合????
就是,两个类之间可以互相交互,但是并不知道互相的具体实现,自己的改变,扩展并不会影响到别人的使用
OO设计原则之四:
尽量使用松耦合,提供软件的弹性,可维护性,可变化性
现在来实现我自己的Observer
首先提供Subject类
public class Subject{
public void addObserver();
public void removeObserver();
public void notifyObserver();
}
public class WeatherData extends Subject{
private List observers;
public WeatherData(){
observers = new ArrayList();
}
public void addObserver(Observer o){
observers.add(o);
}
public void removeObserver(Observer o){
int index = observers.get(o);
if(index >-1){
observers.remove(o);
}
}
public void notifyObserver(){
for(int i=0;i<=observers.size();i++){
observers.get(i).update(this,arg);//这里可以将数据传到Observer中
}
}
}
下面是Observer了,Observer需要有update()方法对数据进行更新,当Subject通知的时候使用,只要Observer向这个Subject注册了(add了)Subject就会通知,一旦取消了(remove了)Subject就不管了,这就是松耦合的体现
public interface Observer{
public void update(Subject s);
}
public class ForCastDisplay implements Observer{
private Subject subject;
private float temperture;
private float wet;
public ForCastDisplay(Subject s){
this.subject = s;
s.addObserver(this);
}
public void update(Subject s){ //可以有数据的话,可以使用,也可以自己去拿
if(s instanceof WeatherData){
temperture = s.getXX();
wet = s.getXX();
}
}
}
这上面是自己实现的观察者模式
JDK在util包中提供它的观察者,Observable 和Observer
注意:Observable是类,Observer是接口
public class Observable{
public void addXX();
public void removeXX();
public void notifyXX();//有两个notify的实现,前面讲了就是因为得到数据的方式不同push是
notify(Observable o, Object arg)
pull是notify(Observable o);
protected void setChanged();//这里要注意
}
setChanged()在notify之前要调用,不然你不能notify到Observer,增加了通知的弹性
你可以在这里看到JDK实现的问题
Observable是类,需要extends不是接口
因此当你有超类,又要成为subject时,有问题
同时因为setChanged()是protected,因此你甚至不能将Observable作为成员来使用,组合碰到了问题
public interface Observer{
update(Observable o);
}
这是Observer需要实现的接口,与自己写的差不多
最后说一点,Subject在通知时的顺序不定,不要写依赖与通知顺序的程序