您的位置:首页 > 其它

设计模式之观察者模式

2015-11-30 11:41 525 查看
一、定义:观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变时,它的所有依赖者都会收到通知,并自动更新。


二、示例:观察者和可观察者之间用松耦合方式结合,可观察者不知道观察者的细节,只知道观察者实现了观察者接口,并用此观察者接口更新观察者。

1、 自定义实现观察者模式。

//可观察者接口,观察者实现此接口,方便观察者的注册与移除
public interface Observable{

//观察者注册方法
public void addObserver(Observer observer);
//观察者的移除方法
public void delObserver(Observer observer);
//可观察者发生变化时调用该方法通知所有观察者
public void notifyObservers();
}

//观察者接口,所有的观察者都必须实现update()方法,以实现观察者接口。
public interface Observer{
//当可观察者状态发生改变时,会通过此方法将状态值(obj)传给观察者,o用来标识是哪个可观察者
public void update(Observable o,Object obj);
}

//某一可观察者,实现可观察者接口
public class Subject implements Observable{
//存储注册此可观察者的观察者集合
private ArrayList<Observer> observers;
//可观察者的状态对象,可改成任意需要的对象
private Object mObject;

public Subject(){
//初始化集合,用于保存所有注册此可观察者的观察者
observers=new ArrayList<Observer>();
}

//注册观察者
public void addObserver(Observer observer){
observers.add(observer);//只需将观察者添加进观察者集合
}

//移除观察者
public void delObserver(Observer observer){
int i=observers.indexOf(o);
if(i>=0){
observers.remove(i);//将观察者从观察者集合中移除
}
}

//通知观察者们,数据已经变化
public void notifyObservers(){
for(int i=0;i<observers.size();i++){
Observer observer = observers.get(i);
observer.update(this,mObject);
}
}

//数据改变时调用的方法,在状态值发生改变并想通知观察者的地方调用
public void dataChanged(){
notifyObservers();
}

//可观察者的其他代码逻辑
......

}

//某一观察者,实现观察者接口
public class DataDisplay implements Observer{
//对可观察者的引用,以便在不需要继续观察的时候将自己从可观察者中移除
private Observerable mSubject;

public DataDisplay(Observable subject){
this.mSubject=subject;
subject.addObserver(this);//将直接注册成为观察者
}

public void update(Observable o,Object obj){
//当可观察者状态发生改变时此方法会被调用,将状态发生变化的可观察者以及状态参数传递过来
//实现自己的代码逻辑
......

}

}


2、 java内置的观察者模式:java.util包中包含了最基本的Observer接口和Observable类,和上面我们自定义的两个接口类似,使用上更方便,而且可以使用推或拉两种方式从可观察者中获取状态值。

① 把对象变成观察者:通过实现观察者接口(java.util.Observer),然后调用任何Observable对象的addObserver()方法将自己注册为观察者;当不想成为观察者时调用deleteObserver()方法就可以了。

② 可观察者发送通知:通过继承java.util.Observable类将自己变为可观察对象,然后先调用setChanged()方法,标记状态已经改变的事实;然后调用notifyObservers()或notifyObservers(Object obj)发送通知。

③ 观察者接收通知:观察者实现了Observer接口后会默认实现update(Observable o,Object obj),当可观察者发送通知时update方法会回调。此方法中将可观察者自身作为第一个变量,好让观察者知道是哪个可观察者通知它的;第二个参数obj就是notifyObservers(Object obj)中的参数obj。

我们注意到,在可观察对象发送通知前必须调用 setChanged()方法设置状态已经改变的事实,然后再调用两种notifyObservers()方法之一才会真正的通知观察者,这样一来,就可以使我们更灵活的应用通知,其实现原理也很简单:

setChanged(){
changed=true;//把changed标志设为true
}

notifyObservers(Object obj){
if(changed){//只会在changed标为"true"时通知观察者
for every observer on the list{
call update(this,obj);
}
}
changed=false;//在通知观察者之后,把changed标志设回false
}


三、总结:java内置的java.util.Observable类虽然使用起来非常简便,但是它也有一些黑暗面,首先,Observable是一个类,而不是接口,甚至没有实现一个接口,这样的话,如果某个类想同时具有Observable类和另一个超类的行为,就会陷入两难;另外,Observable类将关键的方法(如setChanged()方法)保护起来了,除非继承自Observable,否则无法创建Observable实例并组合到自己的对象中来;最后有一点需要注意的是,当有多个观察者时,不可以依赖特定的通知次序,就是说可观察者通知观察者的次序是不固定的,如果依赖通知次序实现某些功能,结果会不尽人意。所以,如果内置的观察者模式能够满足我们的需求是,可以使用内置的观察者模式,毕竟它们已经帮我们实现了很多逻辑,使用起来更方便,但是如果java内置的观察者模式使用时得到了限制,不妨实现自己的观察者模式,毕竟原理我们已经很清楚。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: