觀察者模式

觀察者模式

一侧纯、簡介

觀察者模式(又被稱為發(fā)布-訂閱(Publish/Subscribe)模式,屬于行為型模式的一種,它定義了一種一對多的依賴關(guān)系依鸥,讓多個(gè)觀察者對象同時(shí)監(jiān)聽某一個(gè)主題對象。這個(gè)主題對象在狀態(tài)變化時(shí)悼沈,會通知所有的觀察者對象贱迟,使他們能夠自動更新自己。該模式一個(gè)重要作用就是解耦絮供,將被觀察者和觀察者進(jìn)行解耦衣吠,使他們之間的依賴性更小

二、使用場景

  • 關(guān)聯(lián)行為場景壤靶,需要注意的是關(guān)聯(lián)行為是可拆分的而不是“組合”關(guān)系
  • 事件多級觸發(fā)場景
  • 跨系統(tǒng)的消息交換場景缚俏,如消息隊(duì)列、事件總線的處理機(jī)制

三贮乳、簡單實(shí)現(xiàn)

這里我們以微信公眾號的訂閱為例忧换。公眾號當(dāng)其更新內(nèi)容時(shí)就會推送給訂閱了該公眾號的讀者。

    //被觀察者
    public class Wechat extends Observable{
        public void postNewPublication(String content){
            setChanged();
            notifyObservers(content);
        }
    }

    //觀察者
    public class Reader implements Observer{
       public String name ;

        public Reader(String name) {
            this.name = name;
        }

        @Override
        public void update(Observable o, Object arg) {
            Log.i(TAG, "update: wechat is update content is :"+arg);
        }
    }
    
    public void test(){
        Wechat wechat=new Wechat();
        
        Reader reader1=new Reader("reader1");
        Reader reader2=new Reader("reader2");
        Reader reader3=new Reader("reader3");
        
        wechat.addObserver(reader1);
        wechat.addObserver(reader2);
        wechat.addObserver(reader3);
        
        wechat.postNewPublication("up up up");
    }

這里需要注意的是Observer和Observable是JDK內(nèi)置的類向拆,表示觀察者和被觀察者亚茬。

四、觀察者模式在Android中應(yīng)用

ListView和RecycleView 的notifyDataSetChanged

當(dāng)我們在使用ListView或RecycleView時(shí)如果數(shù)據(jù)發(fā)生變化我們會調(diào)用Adapter的notifyDataSetChanged()方法,如下所示

 public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

在方法內(nèi)部調(diào)用了mDataSetObservable.notifyChanged浓恳,這里的mDataSetObservable是一個(gè)DataSetObservable實(shí)例

    private final DataSetObservable mDataSetObservable = new DataSetObservable();

而DataSetObservable繼承自O(shè)bservable刹缝,我們看下DataSetObservable的notifyChanged方法

public class DataSetObservable extends Observable<DataSetObserver> {

public void notifyChanged() {
        synchronized(mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
 }

可以看到調(diào)用了DataSetObserver的onChanged方法,DataSetObserver是一個(gè)抽類這里mObservers.get(i)獲得的是其子類AdapterDataSetObserver.

class AdapterDataSetObserver extends DataSetObserver {
        private Parcelable mInstanceState = null;
        @Override
        public void onChanged() {
            mDataChanged = true;
            mOldItemCount = mItemCount;
            mItemCount = getAdapter().getCount();
            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                    && mOldItemCount == 0 && mItemCount > 0) {
                AdapterView.this.onRestoreInstanceState(mInstanceState);
                mInstanceState = null;
            } else {
                rememberSyncState();
            }
            checkFocus();
            //重新布局
            requestLayout();
        }

        ...

        public void clearSavedState() {
            mInstanceState = null;
        }
 }

可以看到在AdapterDataSetObserver的onChanged方法中調(diào)用了requestLayout來進(jìn)行重新布局。

BroadcastReceiver

在Android中廣播也是基于觀察者模式的

五颈将、小結(jié)

觀察者模式優(yōu)點(diǎn):

  • 解耦觀察者與被觀察者梢夯,應(yīng)對業(yè)務(wù)變化
  • 增強(qiáng)系統(tǒng)靈活性、可擴(kuò)展性

缺點(diǎn):

  • 在使用時(shí)要考慮開發(fā)效率和運(yùn)行效率吆鹤,程序中包括一個(gè)被觀察者厨疙、多個(gè)觀察者、開發(fā)調(diào)試等內(nèi)容會比較復(fù)雜疑务,且Java中消息通知默認(rèn)是順序執(zhí)行沾凄,如果一個(gè)觀察者卡頓,那么會影響整體執(zhí)行效率知允,在這種情況下一般考慮使用異步的方式撒蟀。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市温鸽,隨后出現(xiàn)的幾起案子保屯,更是在濱河造成了極大的恐慌手负,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姑尺,死亡現(xiàn)場離奇詭異竟终,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)切蟋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門统捶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人柄粹,你說我怎么就攤上這事喘鸟。” “怎么了驻右?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵什黑,是天一觀的道長。 經(jīng)常有香客問我堪夭,道長愕把,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任茵瘾,我火速辦了婚禮礼华,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拗秘。我一直安慰自己圣絮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布雕旨。 她就那樣靜靜地躺著扮匠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凡涩。 梳的紋絲不亂的頭發(fā)上棒搜,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機(jī)與錄音活箕,去河邊找鬼力麸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛育韩,可吹牛的內(nèi)容都是我干的克蚂。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼筋讨,長吁一口氣:“原來是場噩夢啊……” “哼埃叭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起悉罕,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤赤屋,失蹤者是張志新(化名)和其女友劉穎立镶,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體类早,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡媚媒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了莺奔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片欣范。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖令哟,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情妨蛹,我是刑警寧澤屏富,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蛙卤,受9級特大地震影響狠半,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜颤难,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一神年、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧行嗤,春花似錦已日、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栈雳,卻和暖如春护奈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哥纫。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工霉旗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蛀骇。 一個(gè)月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓厌秒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親松靡。 傳聞我的和親對象是個(gè)殘疾皇子简僧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355