設(shè)計模式-觀察者模式

該模式定義了一個一對多的關(guān)系点楼,一個被觀察對象與一群觀察對象存在依賴關(guān)系,一旦這個被觀察對象有什么風(fēng)吹草動卸夕,其他的觀察者就都能收到通知。其實本質(zhì)是被觀察對象通知所有觀察者對象截驮。

軟件系統(tǒng)很多時候需要這樣的情況笑陈,一旦發(fā)生故障,就通知對應(yīng)的系統(tǒng)或模塊侧纯,使之能夠及時處理新锈。

觀察者類圖結(jié)構(gòu)

  • 抽象主題 Subject:提供添加和減少觀察者方法和通知觀察者方法;
  • 具體主題 ConcreteSubject:對抽象主題的實現(xiàn)眶熬,包含一個觀察者的集合[這里是接口哦妹笆,我們是針對接口編程的],用以操作與觀察者之間的互動娜氏;
  • 抽象觀察者 Observer:提供被主題調(diào)用的方法拳缠,一旦主題變動,就調(diào)用這個方法贸弥;
  • 具體觀察者 ConcreteObserver:對抽象觀察者的抽象調(diào)用方法進(jìn)行實現(xiàn)窟坐。

有了上面的類圖,很快就把代碼切出來:

public interface Subject {

    public void attach(Observer observer);
    
    public void detach(Observer observer);
    
    public void notifyObservers();
}

以上就是抽象主題的基本代碼绵疲,大抵上可以完成任務(wù)了

public interface Observer {
    public void update();
}

抽象觀察者哲鸳,這里簡化,只有一個公開方法被主題調(diào)用
接下來把具體的主題構(gòu)造出來盔憨,如下所示


import java.util.ArrayList;
import java.util.List;

public class ConcreteSubject implements Subject{

    //裝載所有觀察者的容器
    private List<Observer> observers=null;
    //構(gòu)造方法里面初始化容器
    public ConcreteSubject() {
        observers=new ArrayList<Observer>();
    }
    
    @Override
    public void attach(Observer observer) {
        if(!observers.contains(observer)){
            observers.add(observer);
        }
    }

    @Override
    public void detach(Observer observer) {
        if(observers.contains(observer)){
            observers.remove(observer);
        }
    }

    @Override
    public void notifyObservers() {
        for(Observer observer:observers){
            observer.update();
        }
    }

}

其主要任務(wù)就是綁定和解綁觀察者徙菠,以及有事通知觀察者,當(dāng)然可以對觀察者進(jìn)行分類郁岩,根據(jù)分類再進(jìn)行通知婿奔。

最后是具體的觀察者,主要工作代碼如下

public class ConcreteObserver implements Observer{

    private String name;
    
    public ConcreteObserver(String name) {
        this.name=name;
    }
    
    @Override
    public void update() {
        System.out.println(this.name+"被調(diào)用了问慎,在時間:"+new Date());
        
    }

}

運(yùn)行下來看看

public class Client {

    public static void main(String[] args) {
        Observer o1=new ConcreteObserver("張三");
        Observer o2=new ConcreteObserver("李四");
        
        Subject subject=new ConcreteSubject();
        subject.attach(o1);
        subject.attach(o2);
        subject.notifyObservers();
        subject.detach(o2);
        subject.notifyObservers();
    }
}

非常完美的實現(xiàn)了主題通知觀察者萍摊。需要注意的是,在具體主題里面的集合容器最好不要使得外界可以修改如叼,以及線程安全方面需要考慮冰木。

另外一種方式把主題作為抽象類,然后關(guān)聯(lián)到抽象觀察者笼恰,而具體主題負(fù)責(zé)把狀態(tài)改變后片酝,調(diào)用抽象的通知方法;
來段代碼實際情況看看挖腰;

import java.util.ArrayList;
import java.util.List;

public abstract class AbstractSubject {

    // 裝載所有觀察者的容器
    private List<Observer> observers = null;

    // 構(gòu)造方法里面初始化容器
    public AbstractSubject() {
        observers = new ArrayList<Observer>();
    }

    public void attach(Observer observer) {
        if (!observers.contains(observer)) {
            observers.add(observer);
        }
    }

    public void detach(Observer observer) {
        if (observers.contains(observer)) {
            observers.remove(observer);
        }

    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
    //具體主題務(wù)必實現(xiàn)這個方法
    protected String state;
    public abstract void change(String newState);
}

這個抽象主題比較能干,把子類要做到事多包攬了练湿,子類的工作就輕松多了猴仑,來看下

public class ConcreteSubject2 extends AbstractSubject{
    @Override
    public void change(String newState) {
        this.state=newState;
        System.out.println("當(dāng)前主題狀態(tài)修改為"+this.state);
        notifyObservers();
    }
}

具體主題就實現(xiàn)了一個方法,頓時輕松,觀察者和上面一樣辽俗,來看下客戶端怎么使用

public class Client {

    public static void main(String[] args) {
        Observer o1=new ConcreteObserver("張三");
        Observer o2=new ConcreteObserver("李四");
        
//      Subject subject=new ConcreteSubject();
//      subject.attach(o1);
//      subject.attach(o2);
//      subject.notifyObservers();
//      subject.detach(o2);
//      subject.notifyObservers();
        
        AbstractSubject subject=new ConcreteSubject2();
        subject.attach(o1);
        subject.attach(o2);
        subject.change("A");
        subject.detach(o2);
        subject.change("B");
    }
}

JDK 自帶了觀察者模式的一些基本類疾渣,可以使用,但最好還是自己造一個更方便崖飘,里面的源碼可以借鑒看看榴捡,考慮的很詳細(xì)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末朱浴,一起剝皮案震驚了整個濱河市吊圾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翰蠢,老刑警劉巖项乒,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異梁沧,居然都是意外死亡檀何,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門廷支,熙熙樓的掌柜王于貴愁眉苦臉地迎上來频鉴,“玉大人,你說我怎么就攤上這事恋拍《饪祝” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵芝囤,是天一觀的道長似炎。 經(jīng)常有香客問我,道長悯姊,這世上最難降的妖魔是什么羡藐? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮悯许,結(jié)果婚禮上仆嗦,老公的妹妹穿的比我還像新娘。我一直安慰自己先壕,他們只是感情好瘩扼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著垃僚,像睡著了一般集绰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谆棺,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天栽燕,我揣著相機(jī)與錄音,去河邊找鬼。 笑死碍岔,一個胖子當(dāng)著我的面吹牛浴讯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔼啦,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼榆纽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了捏肢?” 一聲冷哼從身側(cè)響起奈籽,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎猛计,沒想到半個月后唠摹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奉瘤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年勾拉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片盗温。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡藕赞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卖局,到底是詐尸還是另有隱情斧蜕,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布砚偶,位于F島的核電站批销,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏染坯。R本人自食惡果不足惜均芽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望单鹿。 院中可真熱鬧掀宋,春花似錦、人聲如沸仲锄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽儒喊。三九已至镣奋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間怀愧,已是汗流浹背唆途。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工富雅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肛搬。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像毕贼,于是被迫代替她去往敵國和親温赔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

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