小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

實(shí)用設(shè)計(jì)模式之觀察者模式

 joy_chen 2015-03-28

1.什么是觀察者模式

        觀察者模式是軟件設(shè)計(jì)模式的一種。在此種模式中,一個目標(biāo)物件管理所有相依于它的觀察者物件,并且在它本身的狀態(tài)改變時主動發(fā)出通知。 

2.觀察者模式的實(shí)現(xiàn)

        雖然在Java中提供了現(xiàn)成的Observer和Observable實(shí)現(xiàn),但由于Observable已經(jīng)被實(shí)現(xiàn)成class,所以當(dāng)需要將自己的某個業(yè)務(wù)類實(shí)現(xiàn)成可被觀察的特性時,往往還是得自己來實(shí)現(xiàn),因此下文不再使用Java中的Observable和Observer類,而是自行實(shí)現(xiàn)。

        通常的實(shí)現(xiàn)方式是注冊-通知-取消注冊。代碼如下:

  1. public interface Listener {  
  2.     void onNotify();  
  3. }  
  4.   
  5.   
  6. public class Subject {  
  7.     private List<Listener> listeners;  
  8.     private Object value;  
  9.       
  10.     public Subject(){  
  11.         listeners=new ArrayList<Listener>();  
  12.         value=new Object();  
  13.     }  
  14.       
  15.     public void registe(Listener listener){  
  16.         listeners.add(listener);  
  17.     }  
  18.       
  19.     public void unRegiste(Listener listener){  
  20.         listeners.remove(listener);  
  21.     }  
  22.       
  23.     private void sendNotify(){  
  24.         for(Listener listener:listeners){  
  25.             listener.onNotify();  
  26.         }  
  27.     }  
  28.       
  29.     public Object getValue(){  
  30.         return value;  
  31.     }  
  32.       
  33.     public void setValue(Object value){  
  34.         if (!this.value.equals(value)){  
  35.             this.value=value;  
  36.             sendNotify();  
  37.         }  
  38.     }  
  39. }  


2.1.容器的選擇

        被觀察者需要一個容器來保留注冊進(jìn)來的觀察者引用,上文的代碼中使用了List作為容器,這個容器的選擇會影響到整體的實(shí)現(xiàn)方案。

        通常選擇用一個Array或List容器來存儲,這樣一方面可以做到有序,另一方面在通知時方便遍歷。

        如果不想有重復(fù)的觀察者引用,則要么在注冊時檢查是否已經(jīng)存在于容器中,比如在上文registe()方法中加入contains()的判斷,要么就選擇不可重復(fù)的容器如Set,Map等。這樣的容器本身已經(jīng)包含了對重復(fù)的處理,但也意味著在發(fā)送通知時的順序不是注冊時的先后順序。 

2.2.通知后的數(shù)據(jù)獲取方式

        也就是常說的‘推’或‘拉’。推方式是說變化的數(shù)據(jù)隨著對觀察者的接口調(diào)用以參數(shù)的方式傳遞給觀察者。拉方式是說對觀察者的接口調(diào)用只用于通知數(shù)據(jù)發(fā)生了變化這件事情,由觀察者自行調(diào)用被觀察者的getXXX()方法取得感興趣的數(shù)據(jù)。前者不管三七二十一把變化就推給觀察者了,不管你有用沒用;后者只是盡到通知的義務(wù),你對什么數(shù)據(jù)感興趣就自己來拿。這個要根據(jù)實(shí)際的設(shè)計(jì)情況進(jìn)行決策。

        上文的代碼中使用了拉的方式,當(dāng)value發(fā)生變化時,會通過sendNotify()方法發(fā)送通知給Listener,但通知中未攜帶value的值,而是由Listener一方根據(jù)情況調(diào)用getValue()方法來拉取變化后的新的value值。 

2.3.通知后的取消注冊

        通知后的取消在實(shí)際應(yīng)用中也沒有上述示例代碼這樣簡單。一個典型的需求就是某個Listener要在onNotify()方法執(zhí)行的過程中調(diào)用unRegiste(this)。對這一需求的滿足可以小心的處理sendNotify()方法,也可以通過標(biāo)識位進(jìn)行標(biāo)識,還可以在sendNotify()中不使用原始的容器而是遍歷一個副本,無論怎樣,這個需求很容易發(fā)生,在實(shí)現(xiàn)觀察者模式時要進(jìn)行處理。 

2.4.其他問題

        如果Subject是時間相關(guān)的業(yè)務(wù),就要對每一個listener的運(yùn)行時間加以約束,要能對每一個onNotify的調(diào)用時間進(jìn)行監(jiān)控并處理,以保持對每一個Listener的時間分配在一個合理的范圍內(nèi)?;蛘呤褂卯惒健⒍嗑€程方式調(diào)起onNotify()。

        如果Subject需要實(shí)現(xiàn)按優(yōu)先級進(jìn)行通知,那就要在優(yōu)先級隊(duì)列管理及通知調(diào)度上下功夫了。 

3.總結(jié)

        觀察者模式說得多,用得多,但在實(shí)際工作當(dāng)中,要深入思考而不是完全照搬示例代碼,這也是設(shè)計(jì)模式給我們的,要學(xué)會把它變成自己的經(jīng)驗(yàn)。



    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多