设计模式笔记 - 观察者模式(Observer Pattern)

模式定义

观察者模式(Observer Pattern)定了对象间的一种一对多的依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并自动更新。观察者模式又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式。


模式结构

观察者模式包含如下角色:

  • Subject:目标
  • ConcreteSubject:具体目标
  • Observer:观察者
  • ConcreteObserver:具体观察者

img


模式案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Subject-目标(主题)
public abstract class Subject {
public List<Observer> observers;

public Subject() {
observers = new ArrayList<Observers>();
}

public void attach(Observer observer) {
observers.add(observer);
}

public boolean detach(Observer observer) {
return observers.remove(observer);
}

public abstract void notify();
}

// Observer-观察者 -> 定义共同约定的接口
public interface Observer {
public void update();
}

// ConcreteSubject-具体目标(主题)
public class ConcreteSubject extends Subject {
public void notify(String text) {
for (Observer observer: observers) {
observer.update(text);
}
}
}

// ConcreteObserver-具体观察者
// 观察者1
public class ConcreteObserver1 implements Observer {
private ConcreteSubject concreteSubject;

public ConcreteObserver1(ConcreteSubject concreteSubject) {
this.concreteSubject = concreteSubject;
}

public void update(String text) {
display(text);
}

public void display(String text) {
System.out.println("ConcreteObserver1 get message: " + text);
}
}

// 观察者2
public class ConcreteObserver2 implements Observer {
private ConcreteSubject concreteSubject;

public ConcreteObserver2(ConcreteSubject concreteSubject) {
this.concreteSubject = concreteSubject;
}

public void update(String text) {
display(text);
}

public void display(String text) {
System.out.println("ConcreteObserver2 get message: " + text + ", also can individuation.");
}
}

// 测试类
public class Test {
public static void main(String[] args) {
ConcreateSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver1();
Observer observer2 = new ConcreteObserver2();

// 向目标(主体)注册观察者
subject.attach(observer1);
subject.attach(observer2);

// 向已注册的观察者发送消息
subject.notify("test message - A");
subject.notify("test message - B");
}
}

模式分析

  • 观察者模式描述了如何建立对象与对象之间的依赖关系,如果构造满足这种需求的系统。
  • 这一模式中的关键对象是被观察目标与观察者两者,一个目标可以有任意数目的与之相依赖的观察者,一旦目标的状态发生改变,所有观察者都将得到通知。
  • 作为对这个通知的响应,每个观察者都可以即时更新自己的状态。

观察者模式的优点:

  • 观察者模式可以实现表现层与数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样的表现层作为具体的观察者角色(前提是实现了更新接口)。
  • 观察者模式在观察目标与观察者之间建立一个抽象的耦合。
  • 观察者模式支持广播通信。
  • 观察者模式符合“开闭原则”的要求。

观察者模式的缺点:

  • 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。

适用环境

在以下情况可以使用观察者模式:

  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象….,可以使用观察者模式创建一种链式触发机制


参考资料:

[1] http://blog.csdn.net/hguisu/article/details/7556625

[2] https://design-patterns.readthedocs.io/zh_CN/latest/behavioral_patterns/observer.html