什么是观察者模式
观察者模式是指一种一对多的对象间的联系方式,当一个对象产生某些动作时需要通知其他多个对象做出相应的反应。比如说,当学校开学的时候,老师、学生、后勤管理部门、行政管理部门等都有不同的事情需要完成。比如,学生学要提前订票,收拾行李,保证按时到校;老师需要熟悉下学期教学计划,提前备课;后勤管理部门需要提前检查学生公寓,保证水、电、暖气等供应正常;行政管理部门需要安排好本学期的教学计划,保证学生按时开课等。我们可以选择在学校开课时,向老师、学生、后勤管理部门、行政管理部门发出相同的通知,不同的部门接到通知后会作出不同的反应这种方式来实现这一系列动作。如下图:
我们可以写一个简单的测试程序,如下:
public class School {
//内部维护的观察对象
Student student;
Teacher teacher;
Administration admin;
LogistcsManag logman;
public School(Student stu, Teacher tea, Administration adm, LogistcsManag log) {
this.student = stu;
this.teacher = tea;
this.admin = adm;
this.logman = log;
}
//当发生指定动作时通知观察对象
public void newTerm() {
student.beginWork();
teacher.beginWork();
admin.beginWork();
logman.beginWork();
}
//主函数
public static void main(String[] args) {
Student stu1 = new Student();
Teacher tec1 = new Teacher();
Administration adm1 = new Administration();
LogistcsManag log1 = new LogistcsManag();
School school = new School(stu1, tec1, adm1, log1);
school.newTerm();
}
}
//观察者 -->学生
class Student {
public void beginWork() {
System.out.println("学生需要提前订票,收拾行李,准备开学...");
}
}
//观察者 -->老师
class Teacher {
public void beginWork() {
System.out.println("老师学要熟悉课程计划,提前备课,准备开学...");
}
}
//观察者 -->行政管理部门
class Administration {
public void beginWork() {
System.out.println("行政管理部门需要制定本学期教学计划,准备开学...");
}
}
//观察者 -->后勤管理部门
class LogistcsManag {
public void beginWork() {
System.out.println("后勤管理部门需要检查水、电、暖气等的正常供应,准备开学...");
}
}
以上程序是一种非常简单的实现方式,但也存在一些问题,比如:
- 如何添加或者移除观察者
- 如何添加新的观察者类的实例对象
我们希望达到的目的是对于被观察者来说,它能够不区分观察者的类型,并将它们都看作相同的类型,这样就能够实现统一的管理。具体来说,就是在不同类的基础上进行一层“封装”,让观察者类实现一个共同的接口,在这个接口中定义观察者类的方法,然后在被观察者类中维护一个保存接口对象的集合,对于被观察者来说,这些对象都具有相同的类型,就可以实现统一的操作。具体方案如下:
对上述思路的代码实现:
import java.util.LinkedList;
//被观察者类
class School {
//被观察者类内部需要维护一个观察者类实现的统一接口的集合
private LinkedList<Observer> obser = new LinkedList<Observer>();
//添加观察者
public void addObse(Observer observer) {
obser.add(observer);
}
//移除观察者
public void removeObse(Observer observer) {
obser.remove(observer);
}
//通知被观察者对象
public void newTerm() {
for(Observer obs: obser)
obs.beginWork();
}
public static void main(String[] args) {
School school = new School();
Student stu = new Student();
school.addObse(stu);
Teacher teacher = new Teacher();
school.addObse(teacher);
Administration admin = new Administration();
school.addObse(admin);
LogistcsManag logm = new LogistcsManag();
school.addObse(logm);
school.newTerm();
}
}
//定义观察类需要实现的统一接口
interface Observer {
public void beginWork();
}
//观察者 -->学生
class Student implements Observer{
public void beginWork() {
System.out.println("学生需要提前订票,收拾行李,准备开学...");
}
}
//观察者 -->老师
class Teacher implements Observer{
public void beginWork() {
System.out.println("老师学要熟悉课程计划,提前备课,准备开学...");
}
}
//观察者 -->行政管理部门
class Administration implements Observer{
public void beginWork() {
System.out.println("行政管理部门需要制定本学期教学计划,准备开学...");
}
}
//观察者 -->后勤管理部门
class LogistcsManag implements Observer{
public void beginWork() {
System.out.println("后勤管理部门需要检查水、电、暖气等的正常供应,准备开学...");
}
}
显然,在对观察者进行统一的接口管理后,被观察者可以很方便的添加、移除、通知观察者对象。