观察者模式又叫做发布-订阅(Publish/Subscribe)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自己更新自己。
Observer结构图.png
Subject类,可翻译成为主题或抽象通知者,一般用一个抽象类或者一个接口实现。它把所有对观察者对象的引用保存在一个集合里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
interface Subject {
//添加观察者
void addObserver(Observer obj);
//移除观察者
void deleteObserver(Observer obj);
//当主题方法改变时,这个方法被调用,通知所有的观察者
void notifyObserver();
}
Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。抽象观察者一般用一个抽象类或者一个接口实现,更新接口通常包含一个Update()方法,这个方法叫做更新方法。
interface Observer {
public void update();
}
ConcreteSubject类,叫做具体主题或具体通知者,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的观察者发出通知。这里举例老师给学生布置作业。
public class TeacherSubject implements Subject {
//用来存放和记录观察者
private List observers=new ArrayList();
//记录状态的字符串
private String info;
@Override
public void addObserver(Observer obj) {
observers.add(obj);
}
@Override
public void deleteObserver(Observer obj) {
int i = observers.indexOf(obj);
if(i>=0){
observers.remove(obj);
}
}
@Override
public void notifyObserver() {
for (Observer observer:observers) {
observer.update();
}
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态相协调,具体观察者角色可以保存一个指向具体主题对象的引用。
public class StudentObserver implements Observer {
//保存一个Subject的引用,以后如果可以想取消订阅,有了这个引用会比较方便
private TeacherSubject teacher;
//学生的姓名,用来标识不同的学生对象
private String name;
//构造器用来注册观察者
public StudentObserver(String name,TeacherSubject teacher) {
this.name=name;
this.teacher = teacher;
//每新建一个学生对象,默认添加到观察者的行列
teacher.addObserver(this);
}
@Override
public void update() {
System.out.println(name+"得到作业:"+teacher.getInfo());
}
}
测试用例
public class TestObserver {
public static void main(String []args) throws Exception {
TeacherSubject teacher=new TeacherSubject();
StudentObserver jack=new StudentObserver("jack",teacher);
StudentObserver mark=new StudentObserver("mark",teacher);
teacher.setInfo("测试题1");
teacher.notifyObserver();
teacher.setInfo("测试题2");
teacher.deleteObserver(jack);
teacher.notifyObserver();
}
}
输出结果
jack得到作业:测试题1
mark得到作业:测试题1
mark得到作业:测试题2
观察者模式在android中的应用
首先在Android中,我们往ListView添加数据后,都会调用Adapter的notifyDataChanged()方法,其中使用了观察者模式。
当ListView的数据发生变化时,调用Adapter的notifyDataSetChanged函数,这个函数又会调用DataSetObservable的notifyChanged函数,这个函数会调用所有观察者(AdapterDataSetObserver)的onChanged方法,在onChanged函数中又会调用ListView重新布局的函数使得ListView刷新界面。