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

??觀察者模式定義對(duì)象一對(duì)多的關(guān)系结洼,他希望一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),其他依賴于它的對(duì)象能夠接到通知并執(zhí)行相應(yīng)的處理邏輯叉跛。例如微信訂閱某個(gè)公眾號(hào)松忍,當(dāng)公眾號(hào)發(fā)布新文章時(shí),所有訂閱該公眾號(hào)的人都會(huì)收到文章推送消息筷厘。spring的事件機(jī)制是采用觀察者模式鸣峭,進(jìn)行業(yè)務(wù)的解耦的。
?? 觀察模式簡(jiǎn)單分為被觀察者和觀察者酥艳,實(shí)現(xiàn)原理為被觀察者有一個(gè)存放觀察者的集合摊溶,當(dāng)被觀察者發(fā)生狀態(tài)改變時(shí),通知所有的觀察者充石,觀察者處理相應(yīng)的邏輯莫换。

被觀察者

?? 這里簡(jiǎn)單用一個(gè)類(lèi)來(lái)描述被觀察者,它可以接收觀察者類(lèi)型,和更新?tīng)顟B(tài)拉岁,當(dāng)狀態(tài)更新時(shí)坷剧,會(huì)通知所有觀察者的onMessage()方法,處理相應(yīng)的邏輯喊暖。


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

@Data
public class Subject {
    private List<Observer> observers = new ArrayList<Observer>();

    public void update(){
        notifyObervers();
    }
    
    public void addObserver(Observer observer) {
        observers.add(observer);
    }
    
    private void notifyObervers(){
        for (Observer observer: observers) {
            observer.onMessage();
        }
    }
}

觀察者

這里定義觀察者惫企,它有一個(gè)指定具體名稱的構(gòu)造方法,和一個(gè)onMessage()方法哄啄,在被觀察者狀態(tài)發(fā)生改變時(shí)被調(diào)用

import lombok.Data;

@Data
public class Observer{
    private String name;

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

    public void onMessage() {
        System.out.println(name + "監(jiān)聽(tīng)到發(fā)布事件");
    }
}

客戶端

當(dāng)我們定義好了被觀察者和觀察者雅任,使用一個(gè)類(lèi)來(lái)模擬相應(yīng)的測(cè)試流程风范。
這里定義了一個(gè)被觀察者和兩個(gè)觀察者咨跌,然后被觀察者更新?tīng)顟B(tài),那么其他的觀察者就會(huì)接到通知硼婿,然后處理事件锌半。

public class App {
    public static void main(String[] args) {
        Subject subject = new Subject();

        Observer firstObserver = new Observer("firstObserver");
        Observer secondObserver = new Observer("secondObserver");
        subject.addObserver(firstObserver);
        subject.addObserver(secondObserver);

        subject.update();
    }
}
輸出
firstObserver監(jiān)聽(tīng)到發(fā)布事件
secondObserver監(jiān)聽(tīng)到發(fā)布事件

升級(jí)版本

考慮到被觀察者進(jìn)行狀態(tài)更新時(shí),不需要通知所有觀察者進(jìn)行狀態(tài)更新寇漫,而是只需要關(guān)注它的狀態(tài)更新的觀察者才需要接到通知刊殉。

觀察者

我們先來(lái)定義觀察者的邏輯,這里通過(guò)泛型州胳,來(lái)定義觀察者只關(guān)注具體的被觀察者的實(shí)現(xiàn)记焊。

import lombok.Data;

@Data
public class Observer<T extends Subject>{
    private String name;

    private T subject;

    public Observer (String name, T subject) {
        this.name = name;
        this.subject = subject;
        subject.addObserver(this);
    }

    public void onMessage() {
        System.out.println(this.name + "監(jiān)聽(tīng)到事件");
    }
}

被觀察者

被觀察的notifyObervers()方法,在通知觀察者進(jìn)行狀態(tài)更新時(shí)栓撞,只有該觀察者關(guān)注的是自己的實(shí)現(xiàn)時(shí)遍膜,才更新。

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

@Data
public class Subject {

    private List<Observer> observers = new ArrayList<Observer>();

    public void addObserver(Observer observer) {
        observers.add(observer);
    }

    public void update(){
        notifyObervers();
    }

    public void notifyObervers(){
        for (Observer observer: observers) {
            if (observer.getSubject().getClass() == this.getClass()) {
                observer.onMessage();
            }
        }
    }
}

我們這里定義兩個(gè)被觀察者的實(shí)現(xiàn)類(lèi)瓤湘。

public class FirstSubject extends Subject {}
public class SecondSubject extends Subject {}

客戶端

這里客戶端的使用代碼為,實(shí)例化了一個(gè)FirstSubject對(duì)象和一個(gè)SecondSubject瓢颅。和兩個(gè)Observer對(duì)象,他們都只關(guān)注各自的Subject弛说。在把secondObserver也加到firstSubject對(duì)象的觀察者集合里面挽懦,這時(shí)

public class App {
    public static void main(String[] args) {
        Subject firstSubject = new FirstSubject();
        Subject secondSubject = new SecondSubject();

        Observer<FirstSubject> firstObserver = new Observer<FirstSubject>("firstObserver", (FirstSubject) firstSubject);
        Observer<SecondSubject> secondObserver = new Observer<SecondSubject>("secondObserver", (SecondSubject) secondSubject);

        firstSubject.addObserver(secondObserver);

        firstSubject.update();
    }
}
輸出
firstObserver監(jiān)聽(tīng)到事件

這樣就實(shí)現(xiàn)了一個(gè)泛型類(lèi)的觀察者,這里的實(shí)現(xiàn)感覺(jué)有些蹩腳木人,還需要看看別人時(shí)怎么實(shí)現(xiàn)的信柿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市醒第,隨后出現(xiàn)的幾起案子渔嚷,更是在濱河造成了極大的恐慌,老刑警劉巖淘讥,帶你破解...
    沈念sama閱讀 217,907評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件圃伶,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)窒朋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)搀罢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人侥猩,你說(shuō)我怎么就攤上這事榔至。” “怎么了欺劳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,298評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵唧取,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我划提,道長(zhǎng)枫弟,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,586評(píng)論 1 293
  • 正文 為了忘掉前任鹏往,我火速辦了婚禮淡诗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伊履。我一直安慰自己韩容,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布唐瀑。 她就那樣靜靜地躺著群凶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪哄辣。 梳的紋絲不亂的頭發(fā)上请梢,一...
    開(kāi)封第一講書(shū)人閱讀 51,488評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音柔滔,去河邊找鬼溢陪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛睛廊,可吹牛的內(nèi)容都是我干的形真。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼超全,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼咆霜!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起嘶朱,我...
    開(kāi)封第一講書(shū)人閱讀 39,176評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蛾坯,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后疏遏,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體脉课,經(jīng)...
    沈念sama閱讀 45,619評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡救军,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倘零。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片唱遭。...
    茶點(diǎn)故事閱讀 39,932評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖呈驶,靈堂內(nèi)的尸體忽然破棺而出拷泽,到底是詐尸還是另有隱情,我是刑警寧澤袖瞻,帶...
    沈念sama閱讀 35,655評(píng)論 5 346
  • 正文 年R本政府宣布司致,位于F島的核電站,受9級(jí)特大地震影響聋迎,放射性物質(zhì)發(fā)生泄漏脂矫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評(píng)論 3 329
  • 文/蒙蒙 一砌庄、第九天 我趴在偏房一處隱蔽的房頂上張望羹唠。 院中可真熱鬧,春花似錦娄昆、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,871評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至谷浅,卻和暖如春扒俯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背一疯。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,994評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工撼玄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人墩邀。 一個(gè)月前我還...
    沈念sama閱讀 48,095評(píng)論 3 370
  • 正文 我出身青樓掌猛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親眉睹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子荔茬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評(píng)論 2 354

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