最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java設(shè)計(jì)模式之觀(guān)察者模式解析

 更新時(shí)間:2023年09月19日 09:31:38   作者:小成同學(xué)_  
這篇文章主要介紹了Java設(shè)計(jì)模式之觀(guān)察者模式解析,觀(guān)察者模式,又被稱(chēng)為發(fā)布/訂閱模式,它定義了一種一對(duì)多的依賴(lài)關(guān)系,讓多個(gè)觀(guān)察者對(duì)象同時(shí)監(jiān)聽(tīng)某一個(gè)主題對(duì)象,這個(gè)主題對(duì)象在狀態(tài)變化時(shí),會(huì)通知所有的觀(guān)察者對(duì)象,使他們能夠自動(dòng)更新自己,需要的朋友可以參考下

概述

定義

觀(guān)察者模式,又被稱(chēng)為發(fā)布-訂閱(Publish / Subscribe)模式,它定義了一種一對(duì)多的依賴(lài)關(guān)系,讓多個(gè)觀(guān)察者對(duì)象同時(shí)監(jiān)聽(tīng)某一個(gè)主題對(duì)象。這個(gè)主題對(duì)象在狀態(tài)變化時(shí),會(huì)通知所有的觀(guān)察者對(duì)象,使他們能夠自動(dòng)更新自己。

結(jié)構(gòu)

觀(guān)察者模式 (Observer Pattern) 中有如下角色:

  • Subject:抽象主題(抽象被觀(guān)察者),抽象主題角色把所有觀(guān)察者對(duì)象保存在一個(gè)集合里,每個(gè)主題都可以有任意數(shù)量的觀(guān)察者,抽象主題提供一個(gè)接口,可以增加和刪除觀(guān)察者對(duì)象。
  • ConcreteSubject:具體主題(具體被觀(guān)察者),該角色將有關(guān)狀態(tài)存入具體觀(guān)察者對(duì)象,在具體主題的內(nèi)部狀態(tài)發(fā)生改變時(shí),給所有注冊(cè)過(guò)的觀(guān)察者發(fā)送通知。
  • Observer:抽象觀(guān)察者,是觀(guān)察者的抽象類(lèi),它定義了一個(gè)更新接口,使得在得到主題更改通知時(shí)更新自己。
  • ConcrereObserver:具體觀(guān)察者,實(shí)現(xiàn)抽象觀(guān)察者定義的更新接口,以便在得到主題更改通知時(shí)更新自身的狀態(tài)。

案例實(shí)現(xiàn)

【例】微信公眾號(hào)

在使用微信公眾號(hào)時(shí),大家都會(huì)有這樣的體驗(yàn),當(dāng)你關(guān)注的公眾號(hào)中有新內(nèi)容更新的話(huà),它就會(huì)推送給關(guān)注公眾號(hào)的微信用戶(hù)端。我們使用觀(guān)察者模式來(lái)模擬這樣的場(chǎng)景,微信用戶(hù)就是觀(guān)察者,微信公眾號(hào)是被觀(guān)察者(主題角色),有多個(gè)的微信用戶(hù)關(guān)注了程序猿這個(gè)公眾號(hào)。

類(lèi)圖如下:

代碼如下:

  • 抽象觀(guān)察者類(lèi),里面定義一個(gè)更新的方法
public interface Observer {
    void update(String message);
}
  • 具體觀(guān)察者類(lèi),微信用戶(hù)是觀(guān)察者,里面實(shí)現(xiàn)了更新的方法
public class WeixinUser implements Observer {
    // 微信用戶(hù)名
    private String name;
    public WeixinUser(String name) {
        this.name = name;
    }
    @Override
    public void update(String message) {
        System.out.println(name + "-" + message);
    }
}
  • 抽象主題類(lèi)(被觀(guān)察者),提供了 attach、detach、notify 三個(gè)方法
public interface Subject {
    // 增加訂閱者(觀(guān)察者對(duì)象)
    public void attach(Observer observer);
    // 刪除訂閱者(觀(guān)察者對(duì)象)
    public void detach(Observer observer);
    // 通知訂閱者更新消息
    public void notify(String message);
}
  • 微信公眾號(hào)是具體主題類(lèi)(具體被觀(guān)察者),里面存儲(chǔ)了訂閱該公眾號(hào)的微信用戶(hù),并實(shí)現(xiàn)了抽象主題中的方法
public class SubscriptionSubject implements Subject {
    // 儲(chǔ)存訂閱公眾號(hào)的微信用戶(hù)
    private List<Observer> weixinUserlist = new ArrayList<Observer>();
    @Override
    public void attach(Observer observer) {
        weixinUserlist.add(observer);
    }
    @Override
    public void detach(Observer observer) {
        weixinUserlist.remove(observer);
    }
    @Override
    public void notify(String message) {
        for (Observer observer : weixinUserlist) {
            observer.update(message);
        }
    }
}
  • 客戶(hù)端程序
public class Client {
    public static void main(String[] args) {
        // 1.創(chuàng)建公眾號(hào)對(duì)象
        SubscriptionSubject mSubscriptionSubject = new SubscriptionSubject();
        // 2.創(chuàng)建微信用戶(hù)
        WeiXinUser user1 = new WeiXinUser("孫悟空");
        WeiXinUser user2 = new WeiXinUser("豬悟能");
        WeiXinUser user3 = new WeiXinUser("沙悟凈");
        // 3.訂閱公眾號(hào)
        mSubscriptionSubject.attach(user1);
        mSubscriptionSubject.attach(user2);
        mSubscriptionSubject.attach(user3);
        // 4.公眾號(hào)更新發(fā)出消息給訂閱的微信用戶(hù)
        mSubscriptionSubject.notify("傳智黑馬的專(zhuān)欄更新了");
    }
}

輸出

孫悟空-傳智黑馬的專(zhuān)欄更新了
豬悟能-傳智黑馬的專(zhuān)欄更新了
沙悟凈-傳智黑馬的專(zhuān)欄更新了

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

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

  • 降低了目標(biāo)與觀(guān)察者之間的耦合關(guān)系,兩者之間是抽象耦合關(guān)系。
  • 被觀(guān)察者發(fā)送通知,所有注冊(cè)的觀(guān)察者都會(huì)收到信息【可以實(shí)現(xiàn)廣播機(jī)制】

缺點(diǎn)

  • 如果觀(guān)察者非常多的話(huà),那么所有的觀(guān)察者收到被觀(guān)察者發(fā)送的通知會(huì)耗時(shí)
  • 如果被觀(guān)察者有循環(huán)依賴(lài)的話(huà),那么被觀(guān)察者發(fā)送通知會(huì)使觀(guān)察者循環(huán)調(diào)用,會(huì)導(dǎo)致系統(tǒng)崩潰

使用場(chǎng)景

  • 對(duì)象間存在一對(duì)多關(guān)系,一個(gè)對(duì)象的狀態(tài)發(fā)生改變會(huì)影響其他對(duì)象。
  • 當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴(lài)于另一方面時(shí)。

JDK中提供的實(shí)現(xiàn)-Observable/Observer

在 Java 中,通過(guò) java.util.Observable(抽象主題角色類(lèi)) 和 java.util.Observer(抽象觀(guān)察角色接口) 定義了觀(guān)察者模式,只要實(shí)現(xiàn)它們的子類(lèi)就可以編寫(xiě)觀(guān)察者模式實(shí)例。

Observable 類(lèi)

Observable 類(lèi)是抽象目標(biāo)類(lèi)(被觀(guān)察者),它有一個(gè) Vector 集合成員變量,用于保存所有要通知的觀(guān)察者對(duì)象。

private Vector<Observer> obs;
// 在無(wú)參構(gòu)造方法中賦值
public Observable() {
    obs = new Vector<>();
}

下面來(lái)介紹它最重要的 3 個(gè)方法。

  • void addObserver(Observer o) 方法:用于將新的觀(guān)察者對(duì)象添加到集合中。
public synchronized void addObserver(Observer o) {
    if (o == null)
        throw new NullPointerException();
    // 如果不存在則添加到集合中
    if (!obs.contains(o)) {
        obs.addElement(o);
    }
}
  • void notifyObservers(Object arg) 方法:調(diào)用集合中的所有觀(guān)察者對(duì)象的 update 方法,通知它們數(shù)據(jù)發(fā)生改變。通常越晚加入集合的觀(guān)察者越先得到通知。
public void notifyObservers() {
    notifyObservers(null);
}
			||
            \/
public void notifyObservers(Object arg) {
    Object[] arrLocal;
    synchronized (this) {
        // 只有changed為true才可以執(zhí)行到下面的for循環(huán)
        if (!changed)
            return;
        // 集合轉(zhuǎn)數(shù)組
        arrLocal = obs.toArray();
        // 這個(gè)方法會(huì)將changed置為false 因?yàn)榧磳⑦M(jìn)行通知
        clearChanged();
    }
	// 倒序遍歷數(shù)組 所以這就是為什么越晚加入集合的觀(guān)察者越先得到通知
    for (int i = arrLocal.length-1; i>=0; i--)
        // 逐一通知觀(guān)察者(調(diào)用update方法)
        ((Observer)arrLocal[i]).update(this, arg);
}
  • void setChange() 方法:用來(lái)設(shè)置一個(gè) boolean 類(lèi)型的內(nèi)部標(biāo)志,注明目標(biāo)對(duì)象發(fā)生了變化。當(dāng)它為 true 時(shí),notifyObservers() 才會(huì)通知觀(guān)察者。
protected synchronized void setChanged() {
    changed = true;
}

Observer 接口

Observer 接口是抽象觀(guān)察者,它監(jiān)視目標(biāo)對(duì)象的變化,當(dāng)目標(biāo)對(duì)象發(fā)生變化時(shí),觀(guān)察者得到通知,并調(diào)用 update 方法,進(jìn)行相應(yīng)的工作。

【例】警察抓小偷

警察抓小偷也可以使用觀(guān)察者模式來(lái)實(shí)現(xiàn),警察是觀(guān)察者,小偷是被觀(guān)察者。代碼如下:

小偷是一個(gè)被觀(guān)察者,所以需要繼承 Observable 類(lèi)

public class Thief extends Observable {
    private String name;
    public Thief(String name) {
        this.name = name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void steal() {
        System.out.println("小偷:我偷東西了,有沒(méi)有人來(lái)抓我?。?!");
        super.setChanged(); // changed = true,調(diào)用通知的方法 才會(huì)執(zhí)行觀(guān)察者的update方法
        super.notifyObservers();
    }
}

警察是一個(gè)觀(guān)察者,所以需要讓其實(shí)現(xiàn) Observer 接口

public class Policemen implements Observer {
    private String name;
    public Policemen(String name) {
        this.name = name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    @Override
    public void update(Observable o, Object arg) {
        System.out.println(this.getName() + "警察:" + ((Thief) o).getName() + ",我已經(jīng)盯你很久了,你可以保持沉默,但你所說(shuō)的將成為呈堂證供?。。?);
    }
}

客戶(hù)端代碼

public class Client {
    public static void main(String[] args) {
        // 創(chuàng)建小偷對(duì)象
        Thief t = new Thief("隔壁老王");
        // 創(chuàng)建警察對(duì)象
        Policemen p = new Policemen("小李");
        // 讓警察盯著小偷(訂閱)
        t.addObserver(p);
        // 小偷偷東西(發(fā)布)
        t.steal();
    }
}

輸出

小偷:我偷東西了,有沒(méi)有人來(lái)抓我!??!
小李警察:隔壁老王,我已經(jīng)盯你很久了,你可以保持沉默,但你所說(shuō)的將成為呈堂證供?。?!

到此這篇關(guān)于Java設(shè)計(jì)模式之觀(guān)察者模式解析的文章就介紹到這了,更多相關(guān)Java觀(guān)察者模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java的HttpClient中使用POST請(qǐng)求傳遞參數(shù)兩種常見(jiàn)方式

    Java的HttpClient中使用POST請(qǐng)求傳遞參數(shù)兩種常見(jiàn)方式

    Apache HttpClient為開(kāi)發(fā)者提供了豐富的接口,用于管理HTTP連接并執(zhí)行請(qǐng)求,下面這篇文章主要介紹了Java的HttpClient中使用POST請(qǐng)求傳遞參數(shù)兩種常見(jiàn)方式,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-06-06
  • 基于Redis分布式鎖Redisson及SpringBoot集成Redisson

    基于Redis分布式鎖Redisson及SpringBoot集成Redisson

    這篇文章主要介紹了基于Redis分布式鎖Redisson及SpringBoot集成Redisson,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小小伙伴可以參考一下
    2022-09-09
  • Java 進(jìn)階必備之ssm框架全面整合

    Java 進(jìn)階必備之ssm框架全面整合

    SSM框架是spring MVC ,spring和mybatis框架的整合,是標(biāo)準(zhǔn)的MVC模式,將整個(gè)系統(tǒng)劃分為表現(xiàn)層,controller層,service層,DAO層四層,使用spring MVC負(fù)責(zé)請(qǐng)求的轉(zhuǎn)發(fā)和視圖管理,spring實(shí)現(xiàn)業(yè)務(wù)對(duì)象管理,mybatis作為數(shù)據(jù)對(duì)象的持久化引擎
    2021-10-10
  • 淺談Mybatis版本升級(jí)踩坑及背后原理分析

    淺談Mybatis版本升級(jí)踩坑及背后原理分析

    這篇文章主要介紹了淺談Mybatis版本升級(jí)踩坑及背后原理分析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • Java-JFrame窗體美化方式

    Java-JFrame窗體美化方式

    這篇文章主要介紹了Java-JFrame窗體美化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-11-11
  • 從Maven到Spring Boot實(shí)戰(zhàn)教程

    從Maven到Spring Boot實(shí)戰(zhàn)教程

    本文系統(tǒng)梳理了Java后端開(kāi)發(fā)的核心技術(shù)棧,從Maven項(xiàng)目管理到Spring Boot實(shí)戰(zhàn),從MyBatis持久層到Spring MVC Web開(kāi)發(fā),涵蓋了項(xiàng)目開(kāi)發(fā)的全流程與關(guān)鍵知識(shí)點(diǎn),感興趣的朋友跟隨小編一起看看吧
    2025-11-11
  • Java SwingWorkder使用實(shí)例

    Java SwingWorkder使用實(shí)例

    最近在學(xué)習(xí)Swing,我們都知道在UI表現(xiàn)線(xiàn)程里面長(zhǎng)時(shí)間執(zhí)行操作時(shí),畫(huà)面會(huì)假死,為了能夠讓費(fèi)時(shí)操作不影響畫(huà)面表現(xiàn),就需要用多線(xiàn)程了
    2014-04-04
  • 使用JavaWeb webSocket實(shí)現(xiàn)簡(jiǎn)易的點(diǎn)對(duì)點(diǎn)聊天功能實(shí)例代碼

    使用JavaWeb webSocket實(shí)現(xiàn)簡(jiǎn)易的點(diǎn)對(duì)點(diǎn)聊天功能實(shí)例代碼

    這篇文章主要介紹了使用JavaWeb webSocket實(shí)現(xiàn)簡(jiǎn)易的點(diǎn)對(duì)點(diǎn)聊天功能實(shí)例代碼的相關(guān)資料,內(nèi)容介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-05-05
  • 簡(jiǎn)單了解SpringCloud運(yùn)行原理

    簡(jiǎn)單了解SpringCloud運(yùn)行原理

    這篇文章主要介紹了簡(jiǎn)單了解SpringCloud運(yùn)行原理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • CentOS?7.9服務(wù)器Java部署環(huán)境配置的過(guò)程詳解

    CentOS?7.9服務(wù)器Java部署環(huán)境配置的過(guò)程詳解

    這篇文章主要介紹了CentOS?7.9服務(wù)器Java部署環(huán)境配置,主要包括ftp服務(wù)器搭建過(guò)程、jdk安裝方法以及mysql安裝過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07

最新評(píng)論

砚山县| 莲花县| 津市市| 十堰市| 德州市| 桦甸市| 辰溪县| 廉江市| 根河市| 武山县| 原平市| 乐亭县| 伊吾县| 缙云县| 新民市| 沂水县| 泉州市| 营口市| 巴中市| 西青区| 苍南县| 桃源县| 华安县| 塔河县| 大冶市| 永和县| 阿荣旗| 藁城市| 通海县| 河南省| 吉首市| 平陆县| 平昌县| 黑山县| 武隆县| 南宫市| 察雅县| 贞丰县| 江门市| 八宿县| 凌海市|