定义
定义了对象之间的一对多依赖,让多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者(观察者)都会收到通知并更新。
行为型
适用场景
- 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立的改变和复用。
- 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间大的耦合度。
- 一个对象必须通知其他对象,而并不知道这些对象是谁。
- 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为影响C对象….,可以适用观察者模式创建一种链式触发机制。
优点和缺点
优点
- 观察者和被观察者之间建立一个抽象的耦合
- 观察者模式支持广播通信
缺点
- 观察者时间有过多的细节依赖、提高时间消耗及程序复杂度
- 使用要得当,要避免循环调用
结构
- 抽象主题角色:也叫重选ing目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
- 具体主题角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
- 抽象观察者角色:它是一个抽象类或者接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
- 具体观察者角色:实现首相观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
代码实现
自定义抽象类实现观察者
抽象目标
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public abstract class Subject {
protected List<Observer> observers = new ArrayList<Observer>(); public void add(Observer observer) { observers.add(observer); } public void remove(Observer observer) { observers.remove(observer); } public abstract void notifyObserver();
}
|
具体目标:
1 2 3 4 5 6 7 8 9
| public class ConcreteSubject extends Subject { public void notifyObserver() { System.out.println("具体目标发生改变..."); System.out.println("--------------"); for (Object obs : observers) { ((Observer) obs).response(); } } }
|
抽象观察者
1 2 3
| public interface Observer { void response(); }
|
具体观察者1
1 2 3 4 5
| public class ConcreteObserver1 implements Observer { public void response() { System.out.println("具体观察者1作出反应!"); } }
|
具体观察者2
1 2 3 4 5
| public class ConcreteObserver2 implements Observer { public void response() { System.out.println("具体观察者2作出反应!"); } }
|
结果:
1 2 3 4
| 具体目标发生改变... -------------- 具体观察者1作出反应! 具体观察者2作出反应!
|
UML类图
使用jdk提供类实现观察者
假设一个场景,学生向老师提问问题,那么老师就是观察者,需要观察学生是否有问题并及时做出回应,学生就是被观察者
创建学生类,被观察者,继承jdk的Observable
类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Student extends Observable { private String name;
public Student(String name) { this.name = name; }
public String getName() { return name; }
public void produceQuestion(String question){ System.out.println(name+" 同生提出了一个问题:"+question); setChanged(); notifyObservers(question); }
}
|
观察者老师,继承jdk的Observer
类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Teacher implements Observer {
private String name;
public Teacher(String name) { this.name = name; } @Override public void update(Observable o, Object arg) { Student student = (Student) o; String question = (String) arg; System.out.println(name+" 老师收到了一个 "+student.getName()+"同学提出的问题:"+question); } }
|
具体调用测试:
1 2 3 4 5 6 7 8 9 10 11
| public class Test {
public static void main(String[] args) { Student student = new Student("小明"); Teacher teacher = new Teacher("王老师"); Teacher teacher1 = new Teacher("刘老师"); student.addObserver(teacher); student.addObserver(teacher1); student.produceQuestion("天为什么是蓝的"); } }
|
输出结果:
1 2 3
| 小明 同生提出了一个问题:天为什么是蓝的 刘老师 老师收到了一个 小明同学提出的问题:天为什么是蓝的 王老师 老师收到了一个 小明同学提出的问题:天为什么是蓝的
|
UML类图