一. 前言

1. 定义

Observer Pattern:定义对象间的一种一个对多的依赖关系,当一个对象的状态发送改变时,所以依赖于它的对象都得到通知并被自动更新。

观察者模式又被称作发布/订阅模式。

二. 代码实战

1. 概况

很多人们都在等待放假的信息,它们作为观察者,当放假的信息一出来的时候就需要知道放假的信息。

2. 代码

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
85
86
87
88
89
90
91
92
public class MyClass {
/**
* 抽象的观察者
*/
public interface Observer{
/**
* 收到信息
* @param message
*/
void receiveMessage(String message);
}

/**
* 具体的观察者
*/
public static class Person implements Observer{
public String name;
public String type;

public Person(String name, String type) {
this.name = name;
this.type = type;
}

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

@Override
public void receiveMessage(String message) {
System.out.println(name+"使用"+type+"收到了信息:"+message);
}
}

/**
* 抽象的被观察者
*/
public interface Observable {
//添加观察者
void addObserver(Observer observer);

//移除观察者
void removeObserver(Observer observer);

//通知观察者
void notifyObserver(String message);
}

/**
* 具体的被观察者
*/
public static class DataCenter implements Observable {

//存储观察者
List<Observer> observers = new ArrayList<>();

@Override
public void addObserver(Observer observer) {
observers.add(observer);
}

@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}

@Override
public void notifyObserver(String message) {

//通知所有的观察者们
for (Observer observer : observers) {
observer.receiveMessage(message);
}
}
}


/**
* 测试
*/
public static void main(String[] args) {
Person person1 = new Person("张三", "QQ");
Person person2 = new Person("李四", "微信");
Person person3 = new Person("王二麻", "信息");

DataCenter dataCenter = new DataCenter();
dataCenter.addObserver(person1);
dataCenter.addObserver(person2);
dataCenter.addObserver(person3);
dataCenter.notifyObserver("五月一号放五天假");
}
}
1
2
3
4
//运行效果
张三使用QQ收到了信息:五月一号放五天假
李四使用微信收到了信息:五月一号放五天假
王二麻使用信息收到了信息:五月一号放五天假

3. 系统中的例子

1
2
3
4
5
6
7
8
9
Button button = (Button) findViewById(R.id.button);
//注册观察者
button.setOnClickListener(new View.OnClickListener() {
//观察者实现
@Override
public void onClick(View arg0) {
Log.d("test", "Click button ");
}
});

上面代码中,button就是具体的主题,也就是被观察者;new出来的View.OnClickListenerd对象就是具体的观察者;OnClickListener实际上就是个接口,也就是抽象观察者;通过setOnClickListener把观察者注册到被观察者中。

一旦button捕获的点击事件,即状态发生变化的时候,就会通过回调注册的OnClickListener观察者的onClick方法会来通知观察者,Button状态发生变化。

三. 优缺点以及应用场景

1. 优点

  • 解除观察者与主题之间的耦合。让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。

  • 易于扩展,对同一主题新增观察者时无需修改原有代码。

2. 缺点

  • 依赖关系并未完全解除,抽象主题仍然依赖抽象观察者。

  • 使用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

  • 可能会引起多余的数据通知。

3. 应用场景

  • 当一个对象的改变需要通知其它对象改变时,而且它不知道具体有多少个对象有待改变时。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁
  • 跨系统的消息交换场景,如消息队列、事件总线的处理机制。

参考文章

Android的设计模式-观察者模式