设计模式(15)——观察者模式

本文介绍观察者模式的概念和应用。

基本思想和原则

定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。另外观察者模式又被称为发布/订阅模式。

动机

当一个对象的状态变化会导致其他对象的变化时,可以考虑使用观察者模式。

实现

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
public class Server extends Observable {
private String name;

public Server(String name) {
this.name = name;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public void cpuOverload() {
System.out.println(this.getName() + " CPU overload.");
super.setChanged();
super.notifyObservers("cpu overload");
}

public void diskOverload() {
System.out.println(this.getName() + " disk overload.");
super.setChanged();
super.notifyObservers("disk overload");
}
}

public class Monitor implements Observer {
private String name;

public Monitor(String name) {
this.name = name;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public void update(Observable o, Object arg) {
String msg = (String)arg;
Server server = (Server)o;
if (msg.equalsIgnoreCase("cpu overload")) {
System.out.println(this.getName() + " got cpu overload message of " + server.getName() + ".");
} else if (msg.equalsIgnoreCase("disk overload")) {
System.out.println(this.getName() + " got disk overload message of " + server.getName() + ".");
}
}
}

public class Test {
public static void main(String[] args) {
Server server1 = new Server("Server_1");
Monitor monitor1 = new Monitor("Monitor_1");
Monitor monitor2 = new Monitor("Monitor_2");

server1.addObserver(monitor1);
server1.addObserver(monitor2);
server1.cpuOverload();
server1.diskOverload();
}
}

输出如下:

1
2
3
4
5
6
Server_1 CPU overload.
Monitor_2 got cpu overload message of Server_1.
Monitor_1 got cpu overload message of Server_1.
Server_1 disk overload.
Monitor_2 got disk overload message of Server_1.
Monitor_1 got disk overload message of Server_1.

上面的代码模拟了一个监控器监视服务器状态的场景,这个场景中服务器是被观察者,监控器是观察者。注意Server类继承了Observable类,Observable类中已经实现了addObserverdeleteObservernotifyObservers这几个方法,用于添加观察者,删除观察者和通知观察者,其在内部维护了一个观察者数组,通知观察者时遍历这个观察者数组,一个个通知即可。另外Server类在cpuOverloaddiskOverload两个方法中将CPU过载和磁盘过载的事件通知观察者。

Monitor类实现了Observer接口,这个接口只有一个方法需要实现:

1
void update(Observable o, Object arg);

update方法是在被观察者通知观察者的时候被调用的,在这个方法中观察者会收到两个参数:被观察者对象的引用和一个通知数据参数,观察者在这个方法中对被观察者发生的状态变动做出自己的响应。

Java中对观察者模式已经有了很好的封装,一般情况下我们只需将被观察者继承Observable类,观察者实现Observer接口,然后编写自己的业务逻辑即可,非常方便。

优点

观察者模式建立了一套抽象的事件触发机制,观察者和被观察之间可以独立扩展。

缺点

在使用观察者模式时要注意不要建立过长的观察链,这有可能导致性能问题,出问题时排查也较为困难。