Java 設(shè)計(jì)模式——觀察者模式(Observer Pattern)

image

前言

本來沒想寫前言的爽篷,感覺就是一堆廢話。那就當(dāng)廢話瀏覽一下吧趋艘,只是提醒一下自己一些注意的東西。

在許多博客當(dāng)中看到把觀察者模式又稱呼為發(fā)布-訂閱模式凶朗。其實(shí)我感覺兩者確實(shí)很相似瓷胧,但還是有一丟丟的區(qū)別:

在發(fā)布-訂閱模式中消息的發(fā)送方,叫做發(fā)布者(publishers)棚愤,消息不會(huì)直接發(fā)送給特定的接收者(訂閱者)搓萧。

舉個(gè)例子:比如微信公眾號(hào)杂数。意思就是發(fā)布者和訂閱者不知道對(duì)方的存在,需要一個(gè)第三方組件瘸洛,叫做信息中介揍移,它將訂閱者和發(fā)布者串聯(lián)起來,它過濾和分配所有輸入的消息反肋。(這段從網(wǎng)上找的那伐,大家可以從網(wǎng)上詳細(xì)了解發(fā)布-訂閱模式)這里就不跑題了。

image

一石蔗、簡介

1罕邀、屬于行為型模式:這些設(shè)計(jì)模式特別關(guān)注對(duì)象之間的通信。

2养距、當(dāng)對(duì)象間存在一對(duì)多關(guān)系時(shí)诉探,則使用觀察者模式。比如棍厌,當(dāng)一個(gè)對(duì)象被修改時(shí)肾胯,則會(huì)自動(dòng)通知它的依賴對(duì)象。

3耘纱、意圖:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系敬肚,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都得到通知并被自動(dòng)更新揣炕。

4、主要解決:一個(gè)對(duì)象狀態(tài)改變給其他對(duì)象通知的問題东跪,而且要考慮到易用和低耦合畸陡,保證高度的協(xié)作。

5虽填、何時(shí)使用:一個(gè)對(duì)象(目標(biāo)對(duì)象)的狀態(tài)發(fā)生改變丁恭,所有的依賴對(duì)象(觀察者對(duì)象)都將得到通知,進(jìn)行廣播通知斋日。

6牲览、使用場景

(1)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一個(gè)方面恶守。將這些方面封裝在獨(dú)立的對(duì)象中使它們可以各自獨(dú)立地改變和復(fù)用第献。

(2)一個(gè)對(duì)象的改變將導(dǎo)致其他一個(gè)或多個(gè)對(duì)象也發(fā)生改變,而不知道具體有多少對(duì)象將發(fā)生改變兔港,可以降低對(duì)象之間的耦合度庸毫。

(3)一個(gè)對(duì)象必須通知其他對(duì)象,而并不知道這些對(duì)象是誰衫樊。

(4)需要在系統(tǒng)中創(chuàng)建一個(gè)觸發(fā)鏈飒赃,A對(duì)象的行為將影響B(tài)對(duì)象利花,B對(duì)象的行為將影響C對(duì)象……展懈,可以使用觀察者模式創(chuàng)建一種鏈?zhǔn)接|發(fā)機(jī)制春锋。

7侮措、注意事項(xiàng)

(1)JAVA 中已經(jīng)有了對(duì)觀察者模式的支持類雷酪。

(2)避免循環(huán)引用隅居。

(3)如果順序執(zhí)行蟀架,某一觀察者錯(cuò)誤會(huì)導(dǎo)致系統(tǒng)卡殼重挑,一般采用異步方式踊餐。

image

二藕漱、實(shí)現(xiàn)步驟

(1)實(shí)現(xiàn)方式:

實(shí)現(xiàn)觀察者模式有很多形式欲侮,比較直觀的一種是使用一種“注冊——通知——注銷”的形式。

比如Android中的廣播(不懂a(chǎn)ndroid也沒關(guān)系肋联,把它想象成學(xué)校的廣播就成威蕉,具體看下面例子)

觀察者模式主要角色

抽象觀察者:描述觀察者的公共接口(收到消息的方法),也可以定義為接口(interface)橄仍。

具體觀察者:描述具體觀察者并對(duì)觀察目標(biāo)的改變做出反應(yīng)韧涨。

抽象被觀察者(目標(biāo)):是指被觀察的對(duì)象,描述被觀察者的公共接口(比如通知侮繁、注冊虑粥、注銷等),也可以定義為接口

具體被觀察者(具體目標(biāo)):描述具體的被觀察者宪哩,與觀察者建立聯(lián)系娩贷。當(dāng)狀態(tài)發(fā)生變化時(shí),通知觀察者锁孟。

(2)舉例:

這里舉個(gè)例子:智商有點(diǎn)不夠用彬祖,想不到好的例子,這里就模擬Android四大組件之一的廣播實(shí)現(xiàn)方式品抽。

首先我們要知道Android廣播的大致實(shí)現(xiàn)流程:創(chuàng)建接收者(具體觀察者)繼承廣播(抽象觀察者)储笑,然后注冊廣播(綁定觀察者,建立聯(lián)系)圆恤。廣播發(fā)送者(具體的被觀察者)發(fā)送廣播通知突倍。最后是注銷廣播(解除綁定,斷開聯(lián)系)盆昙。

看起來有點(diǎn)復(fù)雜羽历,換種思路簡單的想象成學(xué)校發(fā)出廣播通知學(xué)生放學(xué)即可。

(3)步驟簡化版:

1淡喜、創(chuàng)建具體被觀察者(學(xué)校廣播)繼承抽象 被觀察者

2窄陡、創(chuàng)建具體觀察者(學(xué)生)繼承抽象觀察者

3、綁定聯(lián)系

4拆火、發(fā)送通知

哈哈 ~跳夭!相信到這里大家可以自己手動(dòng)了實(shí)現(xiàn)了涂圆,下面貼出具體代碼。

image

三币叹、代碼實(shí)現(xiàn)

抽象 被觀察者:Observable.java润歉;具體 被觀察者:SchoolsBroadcast.java

/**
 * Observable.java
 *  抽象被觀察者
 */
abstract class Observable {
     //發(fā)送廣播
    abstract void sendBroadcast(String message);
}

/**
 * SchoolsBroadcast.java
 *  具體的 被觀察者(學(xué)校廣播)
 */
public class SchoolsBroadcast extends Observable{
    //用來存儲(chǔ)觀察者
    private List<Observer> observers = new ArrayList<Observer>();
    @Override
    void sendBroadcast(String message) {
        System.out.println("學(xué)校發(fā)出通知:"+message);
        for(Observer ob:observers) {
            ob.receive(message);
        }
    }
    //綁定觀察者(可以移動(dòng)到抽象被觀察者中)
    public void registerReceiver(Observer observer) {
        observers.add(observer);
    }
    //解綁觀察者(可以移動(dòng)到抽象被觀察者中)
    public void unRegisterReceiver(Observer observer) {
        if(observers.contains(observer)) {
            observers.remove(observer);
        }
    }
}
image.gif

抽象 觀察者:Observer.java;具體 觀察者:StudentA.java颈抚、StudentB.java踩衩、StudentC.java

/**
 * Observer.java
 *  抽象觀察者
 */
abstract class Observer {
    //收到通知
    abstract void receive(String message);
}

/**
 *  StudentA.java
 *  具體的觀察者(學(xué)生A)
 */
public class StudentA extends Observer{
    @Override
    void receive(String message) {
        System.out.println("學(xué)生A收到消息:"+message);
    }
}

/**
 *  StudentB.java
 *  具體的觀察者(學(xué)生B)
 */
public class StudentB extends Observer{
    @Override
    void receive(String message) {
        System.out.println("學(xué)生B收到消息:"+message);
    }
}

/**
 *  StudentC.java
 *  具體的觀察者(學(xué)生C)
 */
public class StudentC extends Observer{
    @Override
    void receive(String message) {
        System.out.println("學(xué)生C收到消息:"+message);
    }
}
image.gif

測試類:Test.java

/**
 * Test.java
 *  測試類
 */
public class Test {
    public static void main(String[] args) {
        //創(chuàng)建被觀察者(學(xué)校廣播)
        SchoolsBroadcast schoolsBroadcast = new SchoolsBroadcast();
        //創(chuàng)建觀察者(學(xué)生)
        StudentA studentA = new StudentA();
        //綁定觀察者 建立聯(lián)系
        schoolsBroadcast.registerReceiver(studentA);
        schoolsBroadcast.registerReceiver(new StudentB());
        schoolsBroadcast.registerReceiver(new StudentC());
        //被觀察者(學(xué)校廣播)發(fā)出通知
        schoolsBroadcast.sendBroadcast("放學(xué)");
        System.out.println("=====================");
        //解綁觀察者(學(xué)生A)
        schoolsBroadcast.unRegisterReceiver(studentA);
        //被觀察者(學(xué)校廣播)發(fā)出通知
        schoolsBroadcast.sendBroadcast("學(xué)生A請(qǐng)假");
    }
}
image.gif
image

例子很簡單、容易忘的可以多寫幾遍贩汉,很容易記住驱富。當(dāng)然面試時(shí)還是賊好用滴!Fノ琛褐鸥!

image

四、總結(jié)

優(yōu)點(diǎn):

1赐稽、觀察者和被觀察者是抽象耦合的叫榕。

2、建立一套觸發(fā)機(jī)制姊舵。.

3晰绎、符合“開閉原則”的要求。

缺點(diǎn):

1括丁、如果一個(gè)被觀察者對(duì)象有很多的直接和間接的觀察者的話荞下,將所有的觀察者都通知到會(huì)花費(fèi)很多時(shí)間。

2史飞、如果在觀察者和觀察目標(biāo)之間有循環(huán)依賴的話尖昏,觀察目標(biāo)會(huì)觸發(fā)它們之間進(jìn)行循環(huán)調(diào)用,可能導(dǎo)致系統(tǒng)崩潰祸憋。

3会宪、觀察者模式?jīng)]有相應(yīng)的機(jī)制讓觀察者知道所觀察的目標(biāo)對(duì)象是怎么發(fā)生變化的肖卧,而僅僅只是知道觀察目標(biāo)發(fā)生了變化蚯窥。

五、Demo地址

https://github.com/DayorNight/DesignPattern

六塞帐、參考文檔

http://www.runoob.com/design-pattern/observer-pattern.html

七拦赠、內(nèi)容推薦

CSDN:https://blog.csdn.net/cs_lwb/article/details/84189465

相關(guān)文章:

《JAVA 設(shè)計(jì)模式——單例模式》

《Java 設(shè)計(jì)模式——工廠模式》

如果你覺得我寫的不錯(cuò)或者對(duì)您有所幫助的話。不妨頂一個(gè)【微笑】葵姥,別忘了點(diǎn)贊荷鼠、收藏、加關(guān)注哈@菩摇允乐!

您的每個(gè)舉動(dòng)都是對(duì)我莫大的支持

image
image

?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末矮嫉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子牍疏,更是在濱河造成了極大的恐慌蠢笋,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳞陨,死亡現(xiàn)場離奇詭異昨寞,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)厦滤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門援岩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掏导,你說我怎么就攤上這事享怀。” “怎么了碘菜?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵凹蜈,是天一觀的道長。 經(jīng)常有香客問我忍啸,道長仰坦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任计雌,我火速辦了婚禮悄晃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凿滤。我一直安慰自己妈橄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布翁脆。 她就那樣靜靜地躺著眷蚓,像睡著了一般。 火紅的嫁衣襯著肌膚如雪反番。 梳的紋絲不亂的頭發(fā)上沙热,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音罢缸,去河邊找鬼篙贸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛枫疆,可吹牛的內(nèi)容都是我干的爵川。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼息楔,長吁一口氣:“原來是場噩夢啊……” “哼寝贡!你這毒婦竟也來了扒披?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤圃泡,失蹤者是張志新(化名)和其女友劉穎谎碍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體洞焙,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蟆淀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了澡匪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熔任。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖唁情,靈堂內(nèi)的尸體忽然破棺而出疑苔,到底是詐尸還是另有隱情,我是刑警寧澤甸鸟,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布惦费,位于F島的核電站,受9級(jí)特大地震影響抢韭,放射性物質(zhì)發(fā)生泄漏薪贫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一刻恭、第九天 我趴在偏房一處隱蔽的房頂上張望瞧省。 院中可真熱鬧,春花似錦鳍贾、人聲如沸鞍匾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橡淑。三九已至,卻和暖如春咆爽,著一層夾襖步出監(jiān)牢的瞬間梁棠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工伍掀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留掰茶,地道東北人暇藏。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓蜜笤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親盐碱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子把兔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

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

  • 設(shè)計(jì)模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計(jì)原則時(shí)需要注意以下幾點(diǎn):a) 高內(nèi)聚沪伙、低耦合和單一職能的“沖突”實(shí)際上,這兩者...
    彥幀閱讀 3,736評(píng)論 0 14
  • 1 場景問題# 1.1 訂閱報(bào)紙的過程## 來考慮實(shí)際生活中訂閱報(bào)紙的過程县好,這里簡單總結(jié)了一下围橡,訂閱報(bào)紙的基本流程...
    七寸知架構(gòu)閱讀 4,598評(píng)論 5 57
  • 【學(xué)習(xí)難度:★★★☆☆,使用頻率:★★★★★】直接出處:觀察者模式梳理和學(xué)習(xí):https://github.com...
    BruceOuyang閱讀 1,515評(píng)論 1 5
  • 【重慶分公司何夢瑤5月13日分享感悟】 前幾天溝通一個(gè)青年人缕贡,在跟她溝通幾度都被堵了回來時(shí)翁授,我心里特別的心痛,因?yàn)?..
    夢瑤閱讀 262評(píng)論 0 0
  • 清晨五點(diǎn)晾咪,當(dāng)這個(gè)城市還在沉睡時(shí)收擦,我們已經(jīng)摸黑起床。六點(diǎn)谍倦,外面依然萬籟俱寂塞赂,我們歡呼雀躍,整裝待發(fā)昼蛀。大巴車關(guān)掉了所有...
    林夕_ym閱讀 866評(píng)論 0 3