简述
观察者模式其实很简单也很常用。比如 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); } } }
|