Java设计模式-观察者(Observer)模式

定义

观察者模式是对象行为模式的一种类型。行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。《GOF设计模式》中是这样定义观察者模式的,Observer模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式有时也被成为发布(publish )-订阅(Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式(Dependents)。一般我更愿意称它为发布-订阅模式,在RxJava中就是采用订阅的方式来命名的,个人认为这种方式在举示例时也更容易理解。

适用情况

以下任一情况下可以使用观察者模式 :

  • 当一个抽象模型有两个方面 , 其中一个方面依赖于另一方面。将这二者封装在独立的对象中以使它们可以各自独立地改变和复用。
  • 当对一个对象的改变需要同时改变其它对象 , 而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之 , 你不希望这些对象是紧密耦合的。

观察者模式举例

事件监听

在Android开发或者其它GUI开发中,事件监听是最常见的一种观察者模式。举一个最常见的按钮Button点击事件,事件源是Button,在观察者模式中它就是一个Observable,监听器EventListener就是一个Observer,Button一旦注册了OnClickListener,点击Button就是触发OnClickListener中的OnClick方法。Button事件源(也就是Observable)有点击动作发生,就会被OnClickListener(Observer)监听到。也许平常开发过程中没有意识到设计模式,事实上设计模式已经应用到我们日常开发的方方面面了。

//按钮(Observer)注册监听器
btn.setOnClickListener(new MyListener());

//监听器(Observable)
private class MyListener implements OnClickListener{
	public void onClick(View v) {
		//TODO something
	}
}

所有的GUI开发中,涉及到事件监听都是使用的观察者模式,也有人叫这种设置监听的方式叫做事件监听器模式,事实上它也是观察者模式的一种类型。

广播

在Android中广播作为四大组件之一,也是最常用的组件之一,事实上广播机制就是使用的观察者模式实现的。在Android Broadcast广播机制这篇文章最后使用观察者模式对广播进行了简单的实现。

定义一个基类叫BroadcastReceiver,里面含有一个抽象方法,让所有继承该类的实现类都实现的一个广播接收的方法onReceiver。

public abstract class BroadcastReceiver {
	public abstract void onReceive();
}

定义一个Activity,实现相应的注册、注销以及发送广播的方法。

public class Activity {
	private List list = new ArrayList();
	//注册广播
	public void registerReceiver(BroadcastReceiver receiver){
		list.add(receiver);
	}
	//解除注册
	public void unregisterReceiver(BroadcastReceiver receiver){
		list.remove(receiver);
	}
	//发送广播
	public void sendBroadcast(){
		for(BroadcastReceiver receiver:list){
			receiver.onReceive();
		}
	}
}

接下来我们定义MyReceiver01、MyReceiver02和MyReceiver03分别继承BroadcastReceiver,实现onReceiver方法,新建一个测试类MyActivity继承Activity。

public class MyActivity extends Activity {

	private MyReceiver01 receiver01=new MyReceiver01();
	private MyReceiver02 receiver02=new MyReceiver02();
	private MyReceiver03 receiver03=new MyReceiver03();
	
	public void method(){
		//注册广播接受者
		registerReceiver(receiver01);
		registerReceiver(receiver02);
		registerReceiver(receiver03);
		//注销receiver02
		unregisterReceiver(receiver02);
		
		//发送广播
		sendBroadcast();
	}
}

有关更详细的介绍可以查看Android Broadcast广播机制这篇博客。

RxJava

RxJava 在 GitHub 主页上的自我介绍是 "a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)。RxJava的异步是通过观察者模式实现的,被观察者是Observable,观察者为Subscriber,也就是订阅者。在RxJava中观察者称为订阅者也许更具有实际意义,就好比订阅报纸吧,如果你订阅了报纸,报社才送报纸到你家里,只要订阅了报纸的人,报社都会送报。

下面是一个RxJava实现的简单示例:

Observable.create(new OnSubscribe() {
	@Override
	public void call(Subscriber subscriber) {
		subscriber.onNext("hello world!");
	}
}).subscribe(new Subscriber() {
	@Override
	public void onNext(String t) {
		System.out.println("onNext:"+t);
	}
	@Override
	public void onCompleted() {
		System.out.println("onCompleted");
	}
	@Override
	public void onError(Throwable e) {
	}
});

RxJava采用的是链式调用,没有任何嵌套,看上去逻辑更加简洁。针对Android开发在github上也有RxAndroid,现在很多博文都在讲RxJava和RxAndroid,它的欢迎程度可见一斑。

自定义观察者模式

自定义观察者模式,首先必须明确如下职能:

  1. 被观察者知道它的观察者。每一个被观察者可以同时被多个观察者观察。被观察者提供添加、删除观察者对象的接口或基类。
  2. 为那些被观察者发生改变时需获得通知的对象定义一个更新接口。
  3. 每个被观察者对象都会将有关状态存入观察者对象中;当它的状态发生改变时,向它的观察者发出通知。
  4. 每个具体的观察者对象都会维护一个被观察者对象的引用,并且储存保持与被观察者的状态一致。每个观察者都要实现观察者的更新接口,以使自身状态与被观察者的状态保持一致

接下来我们自定义一个观察者模式,首先抽象出观察者接口,代码如下:

public interface Observer {
	//接收被观察者的 信息
	void update(Observable obj, Object arg);
}

定义一个被观察者基类,代码如下:

public class Observable {
	//存储所有观察者对象
	private List list=new ArrayList();
	
	//添加观察者对象
	public void addObserver(Observer obj){
		if(obj!=null&&!list.contains(obj)){
			list.add(obj);
		}
	}
	
	//移除观察者
	public void deleteObserver(Observer obj){
		list.remove(obj);
	}
	
	//有行为活动时通知观察者
	public void notifyObservers(Object arg) {
		for(Observer obj:list){
			obj.update(this, arg);
		}
	}
	//有行为活动时通知观察者
	public void notifyObservers(){
		notifyObservers(null);
	}
}

然后定义观察者与被观察者的实现类

//观察者
public class FisherMan implements Observer {
	
	private String name;
	
	public FisherMan(String name){
		this.name=name;
	}

	@Override
	public void update(Observable obj, Object arg) {
		System.out.println(name+" observed the fish is eating "+arg);
	}
}

//被观察者
public class Fish extends Observable {
	
	public String food;
	
	public Fish(String food){
		this.food=food;
	}
	
	public void eating(String food){
		notifyObservers(food);
	}

	public String toString() {
		return "Fish";
	}
}

接下来我们在在main函数中测试一下,代码如下:

public static void main(String[] args) {
	Fish fish=new Fish("food");
	FisherMan man01=new FisherMan("Man01");
	FisherMan man02=new FisherMan("Man02");
	FisherMan man03=new FisherMan("Man03");
	
	fish.addObserver(man01);
	fish.addObserver(man02);
	fish.addObserver(man03);
	fish.deleteObserver(man02);
	
	fish.eating("food");
	
	//Man01 observed the fish is eating food
	//Man03 observed the fish is eating food
	
}

设计模式一般而言有23中,如果有时间希望可以将这23种设计模式一一记录下来学习。

参考资料

GoF设计模式三作者15年后再谈模式

观察者模式

EOF设计模式

Java设计模式

评论

您确定要删除吗?删除之后不可恢复