定义
当对象之间存在一对多的关系时,被依赖的对象发生变化,需要通知到依赖它的所有对象。
举个例子
由于疫情的影响,各地的学校纷纷延迟了开学时间,延迟开学的消息由学校传达给老师和家长(不考虑由老师转发给家长的情况),具体的开学时间也是一样。这个例子中学校与老师和家长之间具有一对多的关系,学校的通知需要都通知到他们,结合观察者模式来code看看。
- 首先定义被观察者:
学校
维护一个 Observer 的数组,老师和家长可以通过 registerObserver 方法注册;学校通过 publishNotice 方法发布通知
import java.util.ArrayList;
import java.util.List;
import observer.consumer.Observer;
public class School {
private String name;
public School(String name) {
this.name = name;
}
private List<Observer> observers = new ArrayList<>();
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void publishNotice(String message) {
System.out.println("I'm school: " + name + ", send message: " + message);
observers.forEach(e -> e.update(message));
}
}
- 定义接口 Observer
public interface Observer {
void update(String message);
}
- 定义观察者:老师
public class Teacher implements Observer {
private String name;
public Teacher(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println("I'm teacher: " + name + ", received message: " + message);
// do something
}
}
- 定义观察者:家长
public class Parent implements Observer {
private String name;
public Parent(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println("I'm parent: " + name + ", received message: " + message);
// do something
}
}
- 最后通过 main 方法执行发布延迟开学的通知
public class Main {
public static void main(String[] args) {
Parent parent = new Parent("ZS");
Teacher teacher = new Teacher("LS");
School school = new School("CSU");
school.registerObserver(parent);
school.registerObserver(teacher);
school.publishNotice("Delay the start of school");
}
}
优缺点
-
优点
- 从上面的例子中看到,观察者与被观察者之间是抽象耦合的。School 类并不直接调用 Teacher & Parent 的 update 方法,而是面向接口编程,调用其接口 Observer 的方法。好处就是假如要添加一个新的观察者,直接继承 Observer 类并注册到 School 即可。
- 建立了一套触发机制。假如 School 要发送各个学生的成绩,同样复用这套机制即可,不需要重新实现。
-
缺点
- 如果观察者过多,那么执行通知要花费很长时间(遍历大数组),不需要的观察者要及时取消注册。
- 如果观察者与被观察者循环依赖,可能导致循环调用,导致系统崩溃。
- 观察者不知道所观察的对象是怎么变化的,只知道变化。