简述

观察者模式其实很简单也很常用。比如 ListView 的数据发生改变时,我们一般会让 Adapter 去调用 notifyDataSetChanged 方法,去通知列表更新视图,实际上原理就是观察者模式相同。

观察者(Observer)
被观察者(Observable)

举个例子:这里有一个舞台,主持人(Observable),观众(Observer),主持人做出某个动作,台下所有观众都能看到(notifyObservers),并做出相应的反应(Observer.update),显然,每个观众的反应都是不一样的。

实现原理

Observer实际上只是个接口类,源码如下:

1
2
3
public interface Observer {
void update(Observable observable, Object data);
}

Observable 核心的成员变量为 Observer 队列,初始数量为 0。Observable 通过 addObserver 去添加观察者,通过 removeObserver 去移除观察者,通过 notifyObservers 去让每个 Observer 依次执行 update 方法。

(可以对应观众入场、观众退场、观众观看舞台动作这些情景)

通知中心

这里,用观察者模式的思路,构造一个功能与 iOS 中 NotificationCenter 相似的类。

  • NotificationCenter 的设定为单例对象。
  • 这里,没有使用系统自带的 Observable,而是直接构造了一个被观察者类 DummyObservable,实际功能与 Observable 相似。
  • 使用 HashMap 去记录多个被观察者,使用被观察者的name作为key值。
  • addObserver、removeObserver、postNotification等方法使用与iOS相似,以便移植。
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
93
94
95
96
97
98
99
100
public class NotificationCenter 
{
private HashMap<String, DummyObservable> observables;
private static NotificationCenter instance = null;

public static NotificationCenter defaultCenter() {
if (instance == null) {
instance = new NotificationCenter();
}
return instance;
}

public NotificationCenter() {
observables = new HashMap<String, DummyObservable>();
}

public void addObserver(String notification, Observer observer) {
DummyObservable observable = observables.get(notification);
if (observable == null) {
observable = new DummyObservable(notification);
observables.put(notification, observable);
}
observable.addObserver(observer);
}

public void removeObserver(String notification, Observer observer) {
DummyObservable observable = observables.get(notification);
if (observable != null) {
observable.removeObserver(observer);
}
}

public void postNotification(String notification, Object object) {
DummyObservable observable = observables.get(notification);
if (observable != null) {
if (object == null) {
observable.notifyObservers();
} else {
observable.notifyObservers(object);
}
}
}

class DummyObservable
{
private String _name;
private List<WeakReference<Observer>> _list = new ArrayList<WeakReference<Observer>>();

DummyObservable(String name) {
_name = name;
}

public void addObserver(Observer observer)
{
for (WeakReference<Observer> item : _list)
{
if (item.get() == observer)
{
return;
}
}
_list.add(new WeakReference<Observer>(observer));
}

public void removeObserver(Observer observer)
{
List<WeakReference<Observer>> iterList = new ArrayList<WeakReference<Observer>>(_list);
for (WeakReference<Observer> item : iterList)
{
if (item.get() == observer)
{
_list.remove(item);
break;
}
}
}

public void notifyObservers(Object object)
{
List<WeakReference<Observer>> iterList = new ArrayList<WeakReference<Observer>>(_list);
for (WeakReference<Observer> item : iterList)
{
Observer observer = item.get();
if (observer == null)
{
_list.remove(item);
Log.i("NotificationCenter", _name + ":WeakReference deleted by GC");
}
else
{
observer.update(null, object);
}
}
}

public void notifyObservers() {
notifyObservers(null);
}
}
}