设计模式之观察者模式

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



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

     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内置的观察者模式使用时得到了限制,不妨实现自己的观察者模式,毕竟原理我们已经很清楚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值