?在Java中通過Observable類和Observer接口實(shí)現(xiàn)了觀察者模式。一個(gè)Observer對(duì)象監(jiān)視著一個(gè)Observable對(duì)象的變化,當(dāng)Observable對(duì)象發(fā)生變化時(shí),Observer得到通知,就可以進(jìn)行相應(yīng)的工作。例如在文檔/視圖結(jié)構(gòu)中,文檔被修改了,視圖就會(huì)得到通知。

??????java.util.Observable中有兩個(gè)方法對(duì)Observer特別重要,一個(gè)是setChange()方法用來設(shè)置一個(gè)內(nèi)部標(biāo)志位注明數(shù)據(jù)發(fā)生了變化;一個(gè)是notifyObservers()方法會(huì)去調(diào)用一個(gè)列表中所有的Observer的update()方法,通知它們數(shù)據(jù)發(fā)生了變化。

??????Observer通過Observable的addObserver()方法把自己添加到這個(gè)列表中。這個(gè)列表雖然由Observable擁有,但Observable并不知道到底有哪些Observer正在觀察等待通知。Observable只提供一個(gè)方法讓Observer能把自己添加進(jìn)列表,并保證會(huì)去通知Observer發(fā)生了變化。通過這種機(jī)制,可以有任意多個(gè)Observer對(duì)Observable進(jìn)行觀察,而不影響Observable的實(shí)現(xiàn)。

?

一個(gè)簡單例子:

import?java.util.Observable;

?

public?class?SimpleObservable?extends?Observable

{

???
private?int?data?=?0;
???
public?int?getData(){?

???????
return?data;

???}


???
public?void?setData(int?i){

???????
if(this.data?!=?i){?this.data?=?i;?setChange();}

??????????notifyObservers();

?????????
//只有在setChange()被調(diào)用后,notifyObservers()才會(huì)去調(diào)用update(),否則什么都不干。???}


???}


}

?

import?java.util.Observable;

import?java.util.Observer;

?

public?class?SimpleObserver?implements?Observer

{

???
public?SimpleObserver(SimpleObservable?so){

??????so.addObserver(
this?);

???}




???
public?void?update(Observable?o,Object?arg/*任意對(duì)象,用于傳遞參數(shù)*/){

??????System.out.println(“Data?has?changed?to”?
+?(SimpleObservable)o.getData());

???}


}


?

public?class?SimpleTest

{

???
public?static?void?main(String[]?args){

??????SimpleObservable?doc?
=?new?SimpleObservable?();

??????SimpleObserver?view?
=?new?SimpleObserver?(doc);

??????doc.setData(
1);

??????doc.setData(
2);

??????doc.setData(
2);

??????doc.setData(
3);?

???}


}


?結(jié)果:

Data has changed to 1

Data has changed to 2? //第二次setData(2)時(shí)由于沒有setChange,所以u(píng)pdate沒被調(diào)用

Data has changed to 3

?

??????Observable類有兩個(gè)私有變量。一個(gè)boolean型的標(biāo)志位,setChange()將它設(shè)為真,只有它為真時(shí),notifyObservers方法才會(huì)調(diào)用Observer的update方法,clearChange()設(shè)標(biāo)志位為假,hasChange返回當(dāng)前標(biāo)志位的值。另一個(gè)是一個(gè)Vector,保存著一個(gè)所有要通知的Observer列表,addObserver添加Observer到列表,deleteObserver從列表中刪除指定Observer,deleteObservers清空列表,countObservers返回列表中Observer的數(shù)目,在Observer對(duì)象銷毀前一定要用deleteObserver將其從列表中刪除,不然因?yàn)檫€存在對(duì)象引用的關(guān)系,Observer對(duì)象不會(huì)被垃圾收集,造成內(nèi)存泄漏,并且已死的Observer仍會(huì)被通知到,有可能造成意料外的錯(cuò)誤,而且隨著列表越來越大,notifyObservers操作也會(huì)越來越慢。???

??????Observable的所有方法都是同步的,保證了在一個(gè)線程對(duì)其標(biāo)志位、列表進(jìn)行操作時(shí),不會(huì)有其它線程也在操作它。

??????Observable的notifyObservers(Object obj)形式可以再調(diào)用update時(shí)將參數(shù)傳進(jìn)去。

通知順序通常時(shí)越晚加入列表的越先通知。update會(huì)被依次調(diào)用,由于一個(gè)update返回后下一個(gè)update才被調(diào)用,這樣當(dāng)update中有大量操作時(shí),最好將其中的工作拿到另一個(gè)線程或者Observer本身同時(shí)也是一個(gè)Thread類,Observer先掛起,在update中被喚醒,這樣會(huì)有一個(gè)隱患,Observer線程還沒來得及掛起,update就被調(diào)用了,通知消息就這樣被錯(cuò)過了,一種解決辦法是在Observer中實(shí)現(xiàn)一個(gè)同步的隊(duì)列結(jié)構(gòu),并有一個(gè)類來封裝參數(shù),update實(shí)現(xiàn)一個(gè)參數(shù)類的對(duì)象把接收到的通知消息的參數(shù)封裝在里面,然后把其加進(jìn)隊(duì)列,run方法從隊(duì)列中移除參數(shù)對(duì)象,并進(jìn)行處理,這保證了沒有通知信息被丟失。

????在多線程時(shí),只有Observer會(huì)與單線程不同,Observable不需任何改變來支持多線程,因?yàn)樗趾芏嘧鳛閱为?dú)線程運(yùn)作的Observer。

?

一個(gè)多線程例子:

import?java.util.*;

?

public?class?SimpleObserverEx?extends?Thread?implements?Observer

{

???Queue?queue;
//利用一個(gè)消息隊(duì)列來接收Observable的通知,保證消息不會(huì)丟失



???
public?void?run(){

??????
while(true){

?????????ArgPack?a?
=?(ArgPack)?queue.dequeue();

?????????Observable?o?
=?a.o;

?????????Object?obj?
=?a.arg;

?????????
//…執(zhí)行相應(yīng)的工作

??????}


???}


?

???
public?void?update(Observable?o,?Object?arg){

??????ArgPack?a?
=?new?ArgPack?(o,arg);

??????queue.queue(a);

???}


}


?

import?java.util.*;?

public?class?Queue?extends?LinkedList{

???
public?synchronized?void?queue(Object?o){

??????addLast(o);?

??????notify();

???}


?

???
public?synchronized?void?dequeue(){

??????
while(this.isEmpty()){

?????????
try{?

????????????wait();

?????????}


?????????
catch(InterruptedException?el){

?????????}


??????}


??????Object?o;

??????
try{?

?????????o?
=this.removeFirst();

??????}


??????
catch(NoSuchElementException){

?????????o?
=?null;

??????}


??????
return?o;

???}
?

}


?

public?class?ArgPack

{

???
public?Observable?o;

???
public?Object?obj;

???
public?ArgPack?(Observable?o,Object?obj){

??????
this.o?=?o;this.obj?=?obj;

???}


}


?

Observable是一個(gè)類而不是一個(gè)接口這限制了它的使用,一個(gè)解決的辦法是在一個(gè)Observable類中把我們的類包裝進(jìn)去(把我們的類實(shí)例當(dāng)作Observable的域),因?yàn)镺bservable中的setChange是一個(gè)protected方法,我們沒法在外面調(diào)用它。所以沒法在我們的類中包裝一個(gè)Observable,但是如果我們的類中同樣也有protected方法,那這個(gè)辦法就無法使用。