Java設(shè)計模式之觀察者模式

概念

??觀察者模式:又稱發(fā)布(publish)-訂閱(Subscribe)模式悬槽、模型(Model)-視圖(View)模式唾那、源(Source)-監(jiān)聽器(Listener)模式或從屬者(Dependents)模式,是一種對象行為型模式喧锦。
??定義對象間的一對多的依賴關(guān)系庞呕,當被觀察者對象進行狀態(tài)改變時扯夭,則所有依賴它的觀察者對象都會得到通知并更新狀態(tài)遵倦。

UML

觀察者模式

角色

  • 抽象主題(Subject):又稱抽象被觀察者(Observable),抽象主題維護一個集合额嘿,用來保存所有觀察者對象的引用瘸恼。提供一個接口,用來添加或刪除觀察者對象册养。
  • 具體主題(ConcreteSubject):又稱具體被觀察者(ConcreteObservable)吨枉,在具體主題狀態(tài)發(fā)生改變時炉抒,給所有注冊該主題的具體觀察者對象發(fā)出通知腮介。
  • 抽象觀察者(Observer):觀察者的抽象類续搀,定義了一個update接口,得到主題更新的通知后坎炼,更新自己愧膀。
  • 具體觀察者(ConcreteObserver):實現(xiàn)抽象觀察者的update接口,給出具體的更新狀態(tài)谣光。

簡單示例

??笑傲江湖中辟邪劍譜一重出江湖檩淋,就引起了各大門派的覬覦,這就是典型的觀察者模式啊萄金。福威鏢局被觀察者蟀悦、五岳劍派各大掌門等人為觀察者,觀察者模式開啟氧敢。

抽象主題(Observable)
java.util庫Observer源碼

package java.util;

public class Observable {
    private boolean changed = false;
    private final ArrayList<Observer> observers;

    public Observable() {
        observers = new ArrayList<>();
    }

    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!observers.contains(o)) {
            observers.add(o);
        }
    }

    public synchronized void deleteObserver(Observer o) {
        observers.remove(o);
    }

    public void notifyObservers() {
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {

        Observer[] arrLocal;

        synchronized (this) {
            if (!hasChanged())
                return;

            arrLocal = observers.toArray(new Observer[observers.size()]);
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            arrLocal[i].update(this, arg);
    }

    public synchronized void deleteObservers() {
        observers.clear();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return observers.size();
    }
}

具體主題(ConcreteSubject)
福威鏢局

package com.bamboolmc.designpattern.ObserverMode;

import java.util.Observable;

public class FuWeiBoard extends Observable{

    //發(fā)布事件--辟邪劍譜重現(xiàn)江湖
    public void publishPiXie(){
        System.out.println("我福威鏢局日戈,辟邪劍譜重現(xiàn)江湖");
        //標志狀態(tài)修改
        setChanged();
        //通知所有觀察者
        notifyObservers();
    }
}

抽象觀察者(Observer)
java.util庫Observer接口源碼

package java.util;

public interface Observer {
    void update(Observable o, Object arg);
}

具體觀察者(ConcreteObserver)
林平之、岳不群福稳、余滄海

package com.bamboolmc.designpattern.ObserverMode;

import java.util.Observable;
import java.util.Observer;

public class LinPingzhi implements Observer {

    public LinPingzhi() {
    }

    @Override
    public void update(Observable o, Object arg) {
        doSomething();

    }

    private void doSomething() {
        System.out.println("我林平之涎拉,這是我家祖?zhèn)鲃Ψǎ ? 先要自*  &^*$*%  神功已成的圆,我終于可以報仇了");
    }
}
package com.bamboolmc.designpattern.ObserverMode;

import java.util.Observable;
import java.util.Observer;

public class YuCanghai implements Observer {
    public YuCanghai() {
    }

    @Override
    public void update(Observable o, Object arg) {
        doSomething();

    }

    private void doSomething() {
        System.out.println("我余滄海鼓拧,江湖傳聞的第一劍譜,是我的越妈!………… 我擦季俩,沒搶到,晦氣梅掠!");
    }
}
package com.bamboolmc.designpattern.ObserverMode;

import java.util.Observable;
import java.util.Observer;

public class YueBuqun implements Observer{
    public YueBuqun() {
    }

    @Override
    public void update(Observable o, Object arg) {
        doSomething();

    }
    private void doSomething(){
        System.out.println("我岳不群酌住,有了劍譜,我就是五岳盟主阎抒! …… \"欲練此功酪我,必先自*\" 咔@%#&*   神功在體,誰敢跟我奪五岳盟主^_^");
    }
}

觀察者模式使用

package com.bamboolmc.designpattern.ObserverMode;

import java.util.Observable;

public class FuWeiBoard extends Observable{

    //發(fā)布事件--辟邪劍譜重現(xiàn)江湖
    public void publishPiXie(){
        System.out.println("我福威鏢局且叁,辟邪劍譜重現(xiàn)江湖");
        //標志狀態(tài)修改
        setChanged();
        //通知所有觀察者
        notifyObservers();
    }
}

輸出結(jié)果

我福威鏢局都哭,辟邪劍譜重現(xiàn)江湖
我岳不群,有了劍譜逞带,我就是五岳盟主欺矫! …… "欲練此功,必先自*" 咔@%#&*   神功在體展氓,誰敢跟我奪五岳盟主^_^
我余滄海穆趴,江湖傳聞的第一劍譜,是我的遇汞!………… 我擦未妹,沒搶到,晦氣勺疼!
我林平之教寂,這是我家祖?zhèn)鲃Ψǎ ? 先要自*  &^*$*%  神功已成执庐,我終于可以報仇了

適用環(huán)境

  • 一個系統(tǒng)多個的對象對某些特定的對象的狀態(tài)或者屬性改變感興趣,就可以采取該模式酪耕。
  • 事件多級觸發(fā)場景。
  • 消息隊列轨淌,事件總線處理機制

作用

??最重要的作用就是解耦迂烁,將被觀察者和觀察者解耦,使其依賴性更小或者毫無依賴递鹉。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盟步,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子躏结,更是在濱河造成了極大的恐慌却盘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異黄橘,居然都是意外死亡兆览,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門塞关,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抬探,“玉大人,你說我怎么就攤上這事帆赢⌒⊙梗” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵椰于,是天一觀的道長怠益。 經(jīng)常有香客問我,道長瘾婿,這世上最難降的妖魔是什么溉痢? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮憋他,結(jié)果婚禮上孩饼,老公的妹妹穿的比我還像新娘。我一直安慰自己竹挡,他們只是感情好镀娶,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著揪罕,像睡著了一般梯码。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上好啰,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天轩娶,我揣著相機與錄音,去河邊找鬼框往。 笑死鳄抒,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的椰弊。 我是一名探鬼主播许溅,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼秉版!你這毒婦竟也來了贤重?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤清焕,失蹤者是張志新(化名)和其女友劉穎并蝗,沒想到半個月后祭犯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡滚停,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年盹憎,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铐刘。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖影晓,靈堂內(nèi)的尸體忽然破棺而出镰吵,到底是詐尸還是另有隱情,我是刑警寧澤挂签,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布疤祭,位于F島的核電站,受9級特大地震影響饵婆,放射性物質(zhì)發(fā)生泄漏勺馆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一侨核、第九天 我趴在偏房一處隱蔽的房頂上張望草穆。 院中可真熱鬧,春花似錦搓译、人聲如沸悲柱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽豌鸡。三九已至,卻和暖如春段标,著一層夾襖步出監(jiān)牢的瞬間涯冠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工逼庞, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛇更,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓赛糟,卻偏偏與公主長得像械荷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子虑灰,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容