一、概念描述
观察者模式属于行为型模式,其意图是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
这一个模式的关键对象是目标(Subject)和观察者(Observer)。一个目标可以有任意数目的依赖它的观察者,一旦目标的状态发生改变,所有的观察者都得到通知,作为对这个通知的响应,每个观察者都将查询目标以使其状态与目标的状态同步。
二、适用场景
观察者模式,用于存在一对多依赖关系的对象间,当被依赖者变化时,通知依赖者全部进行更新。因此,被依赖者,应该有添加/删除依赖者的方法,且可以将添加的依赖者放到一个容器中;且有一个方法去通知依赖者进行更新。
三、观察者模式的结构
观察者模式所涉及的角色有:
抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
四、一个实例
老师有一个电话号码,学生需要知道老师的电话号码以便于在需要的时候拨打,当老师的电话号码发生改变时,学生得到通知,并更新相应的电话记录。在这样的组合中,老师就是一个被观察者(Subject),学生就是需要知道信息的观察者(Observer)。
源码:
抽象主题(Subject)角色:
package com.test.observer;
public interface Subject {
public void attach(Observer o);
public void detach(Observer o);
public void notice();
}
具体主题(ConcreteSubject)角色:
package com.test.observer;
import java.util.Vector;
public class Teacher implements Subject{
private String phone;
private Vector students;
public Teacher() {
phone = "";
students = new Vector();
}
@Override
public void attach(Observer o) {
students.add(o);
}
@Override
public void detach(Observer o) {
students.remove(o);
}
/**
* 当目标状态发生改变时,发布通知给观察者
*/
@Override
public void notice() {
for(int i=0;i<students.size();i++){
((Observer)students.get(i)).update();
}
}
public void setPhone(String phone) {
this.phone = phone;
notice();
}
public String getPhone() {
return phone;
}
}
抽象观察者(Observer)角色:
package com.test.observer;
public interface Observer {
public void update();
}
具体观察者(ConcreteObserver)角色:
package com.test.observer;
public class Student implements Observer{
private int student_id;
private String teacher_phone;
private Teacher teacher;
public Student(int student_id,String teacher_phone) {
// TODO Auto-generated constructor stub
this.student_id = student_id;
this.teacher_phone = teacher_phone;
}
public Student(int student_id,Teacher teacher) {
// TODO Auto-generated constructor stub
this.student_id = student_id;
this.teacher = teacher;
}
/**
* 当收到目标通知后更新
*/
@Override
public void update() {
teacher_phone = teacher.getPhone();
}
public void show(){
System.out.println("id:"+ student_id + " teacher_phone:"+teacher_phone);
}
}
测试主类:
package com.test.observer;
import java.util.Vector;
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
Vector students = new Vector();
Teacher teacher = new Teacher();
for(int i=0;i<10;i++){
Student student = new Student(i,teacher);
students.add(student);
teacher.attach(student);
}
teacher.setPhone("10086-123");
for(int i=0;i<10;i++){
((Student)students.get(i)).show();
}
}
}
运行结果:
id:0 teacher_phone:10086-123
id:1 teacher_phone:10086-123
id:2 teacher_phone:10086-123
id:3 teacher_phone:10086-123
id:4 teacher_phone:10086-123
id:5 teacher_phone:10086-123
id:6 teacher_phone:10086-123
id:7 teacher_phone:10086-123
id:8 teacher_phone:10086-123
id:9 teacher_phone:10086-123
Observer模式的最知名的应用是在MVC结构,Observer模式可以很好的应用在文档和图表程序的制作中。
参考:
http://www.cnblogs.com/java-my-life/archive/2012/05/16/2502279.html
http://www.cnblogs.com/hnrainll/archive/2011/12/29/2305582.html