什么是观察者模式?
观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式。
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.
使用场景是什么
当一个对象的改变需要同时改变其它的一些对象行为时(类似于android中的广播通知),可以考虑使用观察者模式.这种模式通常被用来实现事件处理系统.
观察者模式涉及的角色策略
抽象主题角色:把所有对观察者对象的引用保存在一个集合中,每个抽象主题角色都可以有任意数量的观察者。抽象主题提供一个接口,可以增加和删除观察者角色。一般用一个抽象类和接口来实现。
具体主题角色:在具体主题内部状态改变时,给所有注册过的观察者发出通知。具体主题角色通常用一个子类实现。
抽象观察者角色:为所有具体的观察者定义一个接口,在得到主题的通知时更新自己。
具体观察者角色:该角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。通常用一个子类实现。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。
代码示例
定义抽象的主题角色,即抽象的被观察者,在其中声明方法(添加、移除观察者,通知观察者:
public interface SubjectObservable
{
public void addSubject(Subject subject);
public void removeSubject(Subject subject);
public void notifySubjects(String message);
}
具体主题角色,实现了抽象主题角色的业务:
import java.util.ArrayList;
import java.util.List;
public class ConcreteObservable implements SubjectObservable
{
private List<Subject> list = new ArrayList<Subject>();
@Override
public void addSubject(Subject subject)
{
list.add(subject);
}
@Override
public void removeSubject(Subject subject)
{
list.remove(subject);
}
@Override
public void notifySubjects(String message)
{
// 自动调用实际上是主题进行调用的
for (Subject subject : list)
{
subject.update(message);
}
}
}
抽象观察者角色
public interface Subject
{
public void update(String message);
}
具体观察者角色
public class ConcreteMathSubject implements Subject
{
@Override
public void update(String message)
{
System.out.println("数学科目变化:"+message);
}
}
public class ConcreteEnglishSubject implements Subject
{
@Override
public void update(String message)
{
System.out.println("英语科目变化:"+message);
}
}
编写测试
public class Test
{
public static void main(String[] args)
{
SubjectObservable observable = new ConcreteObservable();
Subject mathSubject = new ConcreteMathSubject();
Subject englishSubject = new ConcreteEnglishSubject();
observable.addSubject(mathSubject);
observable.addSubject(englishSubject);
observable.notifySubjects("初中一年级");
}
}
至此一个简单的观察者模式完成.
在java中为了便于开发者使用观察者模式,相应的推出了对应的api,接下来就用原生的java api实现.
使用步骤如下:
1.观察者SubjectObserver 实现Observer 接口。
2.被观察者SubjectObservable继承Observable 类。
3.观察者SubjectObserver 向被观察者 SubjectObservable 订阅事件(将观察者SubjectObserver添加到被观察者SubjectObservable里面去)。
4.被观察者SubjectObservable数据有改变,通知观察者SubjectObserver相应的数据有改变,作出相应的操作。
5.观察者SubjectObserver 向被观察者 SubjectObservable取消订阅事件(将观察者SubjectObserver从被观察者SubjectObservable中移除)。
代码实现如下:
观察者
import java.util.Observable;
import java.util.Observer;
public class SubjectObserver implements Observer {
@Override
public void update(Observable observable, Object data) {
}
}
被观察者
import java.util.Observable;
public class SubjectObservable extends Observable {
private static SubjectObservable instance = new SubjectObservable();
public static SubjectObservable getInstance() {
return instance;
}
public void notifyDataChange(DataModle modle){
setChanged();//这个方法必须添加,否则notifyObservers内部的逻辑不会执行
notifyObservers(modle);
}
}
数据实体类
public class DataModle {
int data=0;
public int getData(){
return data;
}
public void setData(int data){
this.data=data;
}
}
测试类
import java.util.Observable;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
private SubjectObserver observer = new SubjectObserver() {
@Override
public void update(Observable observable, Object data) {
super.update(observable, data);
//观察者接受到被观察者的通知,来更新自己。
DataModle mData = (DataModle)data;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DataModle mData = new DataModle();
mData.setData(5);
//观察者往被观察者中添加订阅事件。
DataChange.getInstance().addObserver(observer);
SubjectObservable.getInstance().notifyDataChange(mData);
}
@Override
protected void onDestory() {
super.onDestory();
//观察者从被观察者队列中移除
SubjectObservable.getInstance().deleteObserver(observer);
}
}
上述只是一个例子,现实开发中会根据业务定义多个观察者来执行相应的逻辑,写这篇文章的目的希望能够帮助更多的人来了解观察者模式,进而灵活的运用在日常的项目开发中,对于自己也是一种回顾。
使用观察者模式的优缺点
优点:观察者模式在被观察者和观察者之间建立一个抽象的耦合.被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都符合一个抽象观察者的接口。观察者模式支持广播通讯。被观察者会向所有的注册过的观察者发出通知,一个观察者对象只做一件事情,这样在开发中提供了重用性和维护性。
缺点:虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。另外,如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。