一、觀察者模式介紹
在Java中通過Observable類和Observer接口實現了觀察者模式。一個Observer對象監視著一個Observable對象的變化,當Observable對象發生變化時,Observer得到通知,就可以進行相應的工作。
如果畫面A是顯示數據庫里面的數據,而畫面B修改了數據庫里面的數據,那么這時候畫面A就要重新Load。這時候就可以用到觀察者模式
二、觀察者模式實現方法
java.util.Observable中有兩個方法對Observer特別重要
①setChanged()方法
②notifyObservers()方法 / notifyObservers(Object data)方法
?1?/**?
?2??*?If?{@code?hasChanged()}?returns?{@code?true},?calls?the?{@code?update()}?
?3??*?method?for?every?observer?in?the?list?of?observers?using?null?as?the?
?4??*?argument.?Afterwards,?calls?{@code?clearChanged()}.?
?5??*?<p>?
?6??*?Equivalent?to?calling?{@code?notifyObservers(null)}.?
?7??*/??
?8?public?void?notifyObservers()?{??
?9?????notifyObservers(null);??
10?}??
11???
12?/**?
13??*?If?{@code?hasChanged()}?returns?{@code?true},?calls?the?{@code?update()}?
14??*?method?for?every?Observer?in?the?list?of?observers?using?the?specified?
15??*?argument.?Afterwards?calls?{@code?clearChanged()}.?
16??*?
17??*?@param?data?
18??*????????????the?argument?passed?to?{@code?update()}.?
19??*/??
20?@SuppressWarnings("unchecked")??
21?public?void?notifyObservers(Object?data)?{??
22?????int?size?=?0;??
23?????Observer[]?arrays?=?null;??
24?????synchronized?(this)?{??
25?????????if?(hasChanged())?{??
26?????????????clearChanged();??
27?????????????size?=?observers.size();??
28?????????????arrays?=?new?Observer[size];??
29?????????????observers.toArray(arrays);??
30?????????}??
31?????}??
32?????if?(arrays?!=?null)?{??
33?????????for?(Observer?observer?:?arrays)?{??
34?????????????observer.update(this,?data);??
35?????????}??
36?????}??
37?}?
以上兩個方法十分重要
setChanged()方法
——
用來設置一個內部標志位注明數據發生了變化
notifyObservers()方法
/ notifyObservers(Object data)方法 ——
通知所有的Observer數據發生了變化,這時所有的Observer會自動調用復寫好的update(Observable
observable, Object data)方法來做一些處理(比如說畫面數據的更新)。
我們可以看到通知Observer有兩個方法,一個無參,一個有參。那么這個參數有什么作用呢?
其中一個作用:現在我不想通知所有的Observer,而只想其中一個指定的Observer做一些處理,那么就可以傳一個參數作為ID,然后在所有的Observer中判斷,每個Observer判斷只有接收到底參數ID是屬于自己的才做一些處理。
當然參數還有其他作用,我只是舉了個例子。
下面舉個例子加以說明:
?1?import?java.util.Observable;????
?2?/**?
?3??*?被觀察者類?
?4??*/??????
?5?public?class?SimpleObservable?extends?Observable????
?6?{????
?7????private?int?data?=?0;????
?8???????
?9????public?int?getData(){?????
10????????return?data;????
11????}????
12???????
13????public?void?setData(int?i){????
14????????if(this.data?!=?i)?{???
15???????????this.data?=?i;???
16???????????setChanged();????
17???
18???????????//只有在setChange()被調用后,notifyObservers()才會去調用update(),否則什么都不干。??
19???????????notifyObservers();??????
20????????}????
21????}????
22?}?
上面這個類是一個被觀察者類,它繼承了Observable類,表示這個類是可以被觀察的。
然后在setData()方法里面,也就是數據改變的地方,來調用Observable類的setChanged()方法和notifyObservers()方法,表示數據已改變并通知所有的Observer調用它們的update()方法做一些處理。
注意:
?1?????/**?
?2??????*?觀察者類?
?3??????*/????????
?4?????public?class?SimpleObserver?implements?Observer????
?5?????{????
?6????????public?SimpleObserver(SimpleObservable?simpleObservable){????
?7???????????simpleObservable.addObserver(this?);????
?8????????}????
?9???????????
10????????public?void?update(Observable?observable?,Object?data){??//?data為任意對象,用于傳遞參數??
11???????????System.out.println(“Data?has?changed?to”?+?(SimpleObservable)observable.getData());????
12????????}????
13?????}???
通過生成被觀察者(
SimpleObservable類)的實例,來調用addObserver(this)方法讓觀察者(
SimpleObserver類)達到觀察被觀察者(
SimpleObservable類)的目的。
然后還要復寫update()方法,做數據改變后的一些處理。
下面可以寫一個簡單的測試類來測試一下
?1?public?class?SimpleTest????
?2?{????
?3????public?static?void?main(String[]?args){????
?4???????SimpleObservable?doc?=?new?SimpleObservable?();????
?5???????SimpleObserver?view?=?new?SimpleObserver?(doc);????
?6???????doc.setData(1);????
?7???????doc.setData(2);????
?8???????doc.setData(2);????
?9???????doc.setData(3);?????
10????}????
11?}??
運行結果如下
- Data?has?changed?to?1???
- Data?has?changed?to?2??//第二次setData(2)時由于沒有setChange,所以update沒被調用??
- Data?has?changed?to?3??
下面介紹一個Observable類的其他一些屬性和方法
屬性 ——
1?????//?observers是一個List,保存著所有要通知的observer。??????
2?????List<Observer>?observers?=?new?ArrayList<Observer>();??
3?????//?changed是一個boolean型標志位,標志著數據是否改變了。??
4?????boolean?changed?=?false;??
方法 ——
?1?????//?添加一個Observer到列表observers中??
?2?????public?void?addObserver(Observer?observer)?{??
?3?????????if?(observer?==?null)?{??
?4?????????????throw?new?NullPointerException();??
?5?????????}??
?6?????????synchronized?(this)?{??
?7?????????????if?(!observers.contains(observer))??
?8?????????????????observers.add(observer);??
?9?????????}??
10?????}??
11???????
12?????//?從列表observers中刪除一個observer??
13???????
14?????public?synchronized?void?deleteObserver(Observer?observer)?{??
15?????????observers.remove(observer);??
16?????}??
17???????
18?????//?清空列表observers??
19?????public?synchronized?void?deleteObservers()?{??
20?????????observers.clear();??
21?????}??
22???????
23?????//?返回列表observers中observer的個數??
24???????
25?????public?int?countObservers()?{??
26?????????return?observers.size();??
27?????}??
28???????
29???????
30?????//?重置數據改變標志位為未改變??
31?????protected?void?clearChanged()?{???
32?????changed?=?false;??
33?????}??
34???????
35?????//?將數據改變標志位設置為改變??
36???????
37?????protected?void?setChanged()?{???
38?????????changed?=?true;??
39?????}??
40???????
41???????
42?????//?判斷標志位的值??
43?????public?boolean?hasChanged()?{???
44?????????return?changed;??
45?????}??
46???????
47?????//?通知所有observer(無參)??
48?????public?void?notifyObservers()?{??
49?????????notifyObservers(null);??
50?????}??
51?????//?通知所有observer(有參)??
52?????@SuppressWarnings("unchecked")??
53?????public?void?notifyObservers(Object?data)?{???
54?????????int?size?=?0;???
55?????????Observer[]?arrays?=?null;???
56?????????synchronized?(this)?{???
57?????????????if?(hasChanged())?{???
58?????????????????clearChanged();???
59?????????????????size?=?observers.size();??
60?????????????????arrays?=?new?Observer[size];???
61?????????????????observers.toArray(arrays);???
62?????????????}???
63?????????}???
64?????????if?(arrays?!=?null)?{???
65?????????????for?(Observer?observer?:?arrays)?{???
66?????????????????observer.update(this,?data);???
67?????????????}???
68?????????}??
69?????}??
注意:在Observer對象銷毀前一定要用deleteObserver將其從列表中刪除,也就是在onDestroy()方法中調用deleteObserver()方法。
不然因為還存在對象引用的關系,Observer對象不會被垃圾收集,造成內存泄漏,并且已死的Observer仍會被通知到,有可能造成意料外的錯誤,而且隨著列表越來越大,notifyObservers操作也會越來越慢。
下面2個工程是Observable與Observer的經典運用,是android實現的單指拖動放大圖片的操作
兩個例子:
http://download.csdn.net/detail/tianjf0514/4237628
http://download.csdn.net/download/tianjf0514/4237634