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

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

 更新時(shí)間:2023年07月17日 08:30:31   作者:demo007x  
觀察者模式是一種行為設(shè)計(jì)模式, 允許你定義一種訂閱機(jī)制, 可在對象事件發(fā)生時(shí)通知多個(gè) “觀察” 該對象的其他對象,下面這篇文章主要給大家介紹了關(guān)于圖解Go觀察者模式的相關(guān)資料,需要的朋友可以參考下

意圖

觀察者模式是一種行為設(shè)計(jì)模式, 允許你定義一種訂閱機(jī)制, 可在對象事件發(fā)生時(shí)通知多個(gè) “觀察” 該對象的其他對象。

問題

假如你有兩種類型的對象: 顧客商店 。 顧客對某個(gè)特定品牌的產(chǎn)品非常感興趣 (例如最新型號的 iPhone 手機(jī)), 而該產(chǎn)品很快將會(huì)在商店里出售。

顧客可以每天來商店看看產(chǎn)品是否到貨。 但如果商品尚未到貨時(shí), 絕大多數(shù)來到商店的顧客都會(huì)空手而歸。

前往商店和發(fā)送垃圾郵件

另一方面, 每次新產(chǎn)品到貨時(shí), 商店可以向所有顧客發(fā)送郵件 (可能會(huì)被視為垃圾郵件)。 這樣, 部分顧客就無需反復(fù)前往商店了, 但也可能會(huì)惹惱對新產(chǎn)品沒有興趣的其他顧客。

我們似乎遇到了一個(gè)矛盾: 要么讓顧客浪費(fèi)時(shí)間檢查產(chǎn)品是否到貨, 要么讓商店浪費(fèi)資源去通知沒有需求的顧客。

解決方案

擁有一些值得關(guān)注的狀態(tài)的對象通常被稱為目標(biāo), 由于它要將自身的狀態(tài)改變通知給其他對象, 我們也將其稱為發(fā)布者 (publisher)。 所有希望關(guān)注發(fā)布者狀態(tài)變化的其他對象被稱為訂閱者 (subscribers)。

觀察者模式建議你為發(fā)布者類添加訂閱機(jī)制, 讓每個(gè)對象都能訂閱或取消訂閱發(fā)布者事件流。 不要害怕! 這并不像聽上去那么復(fù)雜。 實(shí)際上, 該機(jī)制包括

1) 一個(gè)用于存儲(chǔ)訂閱者對象引用的列表成員變量;

2) 幾個(gè)用于添加或刪除該列表中訂閱者的公有方法;

訂閱機(jī)制允許對象訂閱事件通知。

現(xiàn)在, 無論何時(shí)發(fā)生了重要的發(fā)布者事件, 它都要遍歷訂閱者并調(diào)用其對象的特定通知方法。

實(shí)際應(yīng)用中可能會(huì)有十幾個(gè)不同的訂閱者類跟蹤著同一個(gè)發(fā)布者類的事件, 你不會(huì)希望發(fā)布者與所有這些類相耦合的。 此外如果他人會(huì)使用發(fā)布者類, 那么你甚至可能會(huì)對其中的一些類一無所知。

因此, 所有訂閱者都必須實(shí)現(xiàn)同樣的接口, 發(fā)布者僅通過該接口與訂閱者交互。 接口中必須聲明通知方法及其參數(shù), 這樣發(fā)布者在發(fā)出通知時(shí)還能傳遞一些上下文數(shù)據(jù)。

發(fā)布者調(diào)用訂閱者對象中的特定通知方法來通知訂閱者。

如果你的應(yīng)用中有多個(gè)不同類型的發(fā)布者, 且希望訂閱者可兼容所有發(fā)布者, 那么你甚至可以進(jìn)一步讓所有發(fā)布者遵循同樣的接口。 該接口僅需描述幾個(gè)訂閱方法即可。 這樣訂閱者就能在不與具體發(fā)布者類耦合的情況下通過接口觀察發(fā)布者的狀態(tài)。

真實(shí)世界類比

雜志和報(bào)紙訂閱。

如果你訂閱了一份雜志或報(bào)紙, 那就不需要再去報(bào)攤查詢新出版的刊物了。 出版社 (即應(yīng)用中的 “發(fā)布者”) 會(huì)在刊物出版后 (甚至提前) 直接將最新一期寄送至你的郵箱中。

出版社負(fù)責(zé)維護(hù)訂閱者列表, 了解訂閱者對哪些刊物感興趣。 當(dāng)訂閱者希望出版社停止寄送新一期的雜志時(shí), 他們可隨時(shí)從該列表中退出。

觀察者模式結(jié)構(gòu)

  • 發(fā)布者 (Publisher) 會(huì)向其他對象發(fā)送值得關(guān)注的事件。 事件會(huì)在發(fā)布者自身狀態(tài)改變或執(zhí)行特定行為后發(fā)生。 發(fā)布者中包含一個(gè)允許新訂閱者加入和當(dāng)前訂閱者離開列表的訂閱構(gòu)架。
  • 當(dāng)新事件發(fā)生時(shí), 發(fā)送者會(huì)遍歷訂閱列表并調(diào)用每個(gè)訂閱者對象的通知方法。 該方法是在訂閱者接口中聲明的。
  • 訂閱者 (Subscriber) 接口聲明了通知接口。 在絕大多數(shù)情況下, 該接口僅包含一個(gè) update更新方法。 該方法可以擁有多個(gè)參數(shù), 使發(fā)布者能在更新時(shí)傳遞事件的詳細(xì)信息。
  • 具體訂閱者 (Concrete Subscribers) 可以執(zhí)行一些操作來回應(yīng)發(fā)布者的通知。 所有具體訂閱者類都實(shí)現(xiàn)了同樣的接口, 因此發(fā)布者不需要與具體類相耦合。
  • 訂閱者通常需要一些上下文信息來正確地處理更新。 因此, 發(fā)布者通常會(huì)將一些上下文數(shù)據(jù)作為通知方法的參數(shù)進(jìn)行傳遞。 發(fā)布者也可將自身作為參數(shù)進(jìn)行傳遞, 使訂閱者直接獲取所需的數(shù)據(jù)。
  • 客戶端 (Client) 會(huì)分別創(chuàng)建發(fā)布者和訂閱者對象, 然后為訂閱者注冊發(fā)布者更新。

偽代碼

在本例中, 觀察者模式允許文本編輯器對象將自身的狀態(tài)改變通知給其他服務(wù)對象。

將對象中發(fā)生的事件通知給其他對象。

訂閱者列表是動(dòng)態(tài)生成的: 對象可在運(yùn)行時(shí)根據(jù)程序需要開始或停止監(jiān)聽通知。

在本實(shí)現(xiàn)中, 編輯器類自身并不維護(hù)訂閱列表。 它將工作委派給專門從事此工作的一個(gè)特殊幫手對象。 你還可將該對象升級為中心化的事件分發(fā)器, 允許任何對象成為發(fā)布者。

只要發(fā)布者通過同樣的接口與所有訂閱者進(jìn)行交互, 那么在程序中新增訂閱者時(shí)就無需修改已有發(fā)布者類的代碼。

觀察者模式適合應(yīng)用場景

當(dāng)一個(gè)對象狀態(tài)的改變需要改變其他對象, 或?qū)嶋H對象是事先未知的或動(dòng)態(tài)變化的時(shí), 可使用觀察者模式。

當(dāng)你使用圖形用戶界面類時(shí)通常會(huì)遇到一個(gè)問題。 比如, 你創(chuàng)建了自定義按鈕類并允許客戶端在按鈕中注入自定義代碼, 這樣當(dāng)用戶按下按鈕時(shí)就會(huì)觸發(fā)這些代碼。

觀察者模式允許任何實(shí)現(xiàn)了訂閱者接口的對象訂閱發(fā)布者對象的事件通知。 你可在按鈕中添加訂閱機(jī)制, 允許客戶端通過自定義訂閱類注入自定義代碼。

當(dāng)應(yīng)用中的一些對象必須觀察其他對象時(shí), 可使用該模式。 但僅能在有限時(shí)間內(nèi)或特定情況下使用。

訂閱列表是動(dòng)態(tài)的, 因此訂閱者可隨時(shí)加入或離開該列表。

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

  • 仔細(xì)檢查你的業(yè)務(wù)邏輯, 試著將其拆分為兩個(gè)部分: 獨(dú)立于其他代碼的核心功能將作為發(fā)布者; 其他代碼則將轉(zhuǎn)化為一組訂閱類。

  • 聲明訂閱者接口。 該接口至少應(yīng)聲明一個(gè) update方法。

  • 聲明發(fā)布者接口并定義一些接口來在列表中添加和刪除訂閱對象。 記住發(fā)布者必須僅通過訂閱者接口與它們進(jìn)行交互。

  • 確定存放實(shí)際訂閱列表的位置并實(shí)現(xiàn)訂閱方法。 通常所有類型的發(fā)布者代碼看上去都一樣, 因此將列表放置在直接擴(kuò)展自發(fā)布者接口的抽象類中是顯而易見的。 具體發(fā)布者會(huì)擴(kuò)展該類從而繼承所有的訂閱行為。

    但是, 如果你需要在現(xiàn)有的類層次結(jié)構(gòu)中應(yīng)用該模式, 則可以考慮使用組合的方式: 將訂閱邏輯放入一個(gè)獨(dú)立的對象, 然后讓所有實(shí)際訂閱者使用該對象。

  • 創(chuàng)建具體發(fā)布者類。 每次發(fā)布者發(fā)生了重要事件時(shí)都必須通知所有的訂閱者。

  • 在具體訂閱者類中實(shí)現(xiàn)通知更新的方法。 絕大部分訂閱者需要一些與事件相關(guān)的上下文數(shù)據(jù)。 這些數(shù)據(jù)可作為通知方法的參數(shù)來傳遞。

    但還有另一種選擇。 訂閱者接收到通知后直接從通知中獲取所有數(shù)據(jù)。 在這種情況下, 發(fā)布者必須通過更新方法將自身傳遞出去。 另一種不太靈活的方式是通過構(gòu)造函數(shù)將發(fā)布者與訂閱者永久性地連接起來。

  • 客戶端必須生成所需的全部訂閱者, 并在相應(yīng)的發(fā)布者處完成注冊工作。

觀察者模式優(yōu)缺點(diǎn)

  • 開閉原則。 你無需修改發(fā)布者代碼就能引入新的訂閱者類 (如果是發(fā)布者接口則可輕松引入發(fā)布者類)。

  • 你可以在運(yùn)行時(shí)建立對象之間的聯(lián)系。

  • 訂閱者的通知順序是隨機(jī)的。

與其他模式的關(guān)系

  • 責(zé)任鏈模式命令模式、 中介者模式觀察者模式 用于處理請求發(fā)送者和接收者之間的不同連接方式:

    • 責(zé)任鏈按照順序?qū)⒄埱髣?dòng)態(tài)傳遞給一系列的潛在接收者, 直至其中一名接收者對請求進(jìn)行處理。
    • 命令在發(fā)送者和請求者之間建立單向連接。
    • 中介者清除了發(fā)送者和請求者之間的直接連接, 強(qiáng)制它們通過一個(gè)中介對象進(jìn)行間接溝通。
    • 觀察者允許接收者動(dòng)態(tài)地訂閱或取消接收請求。
  • 中介者和觀察者 之間的區(qū)別往往很難記住。 在大部分情況下, 你可以使用其中一種模式, 而有時(shí)可以同時(shí)使用。 讓我們來看看如何做到這一點(diǎn)。

    中介者的主要目標(biāo)是消除一系列系統(tǒng)組件之間的相互依賴。 這些組件將依賴于同一個(gè)中介者對象。 觀察者的目標(biāo)是在對象之間建立動(dòng)態(tài)的單向連接, 使得部分對象可作為其他對象的附屬發(fā)揮作用。

    有一種流行的中介者模式實(shí)現(xiàn)方式依賴于觀察者。 中介者對象擔(dān)當(dāng)發(fā)布者的角色, 其他組件則作為訂閱者, 可以訂閱中介者的事件或取消訂閱。 當(dāng)中介者以這種方式實(shí)現(xiàn)時(shí), 它可能看上去與觀察者非常相似。

    當(dāng)你感到疑惑時(shí), 記住可以采用其他方式來實(shí)現(xiàn)中介者。 例如, 你可永久性地將所有組件鏈接到同一個(gè)中介者對象。 這種實(shí)現(xiàn)方式和觀察者并不相同, 但這仍是一種中介者模式。

    假設(shè)有一個(gè)程序, 其所有的組件都變成了發(fā)布者, 它們之間可以相互建立動(dòng)態(tài)連接。 這樣程序中就沒有中心化的中介者對象, 而只有一些分布式的觀察者。

代碼示例

Go設(shè)計(jì)模式之觀察者模式講解和代碼示例_Golang_腳本之家 (jb51.net)

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

相關(guān)文章

  • Go語言常見數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)詳解

    Go語言常見數(shù)據(jù)結(jié)構(gòu)的實(shí)現(xiàn)詳解

    這篇文章主要為大家學(xué)習(xí)介紹了Go語言中的常見數(shù)據(jù)結(jié)構(gòu)(channal、slice和map)的實(shí)現(xiàn),文中的示例代碼簡潔易懂,需要的可以參考一下
    2023-07-07
  • golang高并發(fā)系統(tǒng)限流策略漏桶和令牌桶算法源碼剖析

    golang高并發(fā)系統(tǒng)限流策略漏桶和令牌桶算法源碼剖析

    這篇文章主要介紹了golang高并發(fā)系統(tǒng)限流策略漏桶和令牌桶算法源碼剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 使用Go語言計(jì)算字符串編輯距離的代碼實(shí)現(xiàn)

    使用Go語言計(jì)算字符串編輯距離的代碼實(shí)現(xiàn)

    在自然語言處理、拼寫糾錯(cuò)、模糊搜索等場景中,我們經(jīng)常需要衡量兩個(gè)字符串之間的相似度,編輯距離(Edit Distance)  就是一個(gè)經(jīng)典的衡量方式,它描述了將一個(gè)字符串轉(zhuǎn)換為另一個(gè)字符串所需的最少操作次數(shù),本文給大家介紹了如何使用Go語言計(jì)算字符串編輯距離
    2025-07-07
  • Go 使用os包操作環(huán)境變量的方法

    Go 使用os包操作環(huán)境變量的方法

    環(huán)境變量通常在程序啟動(dòng)時(shí)就已設(shè)置好,在需要的時(shí)候隨時(shí)讀取,Go使用簡單的幾個(gè)函數(shù)就可以對環(huán)境變量進(jìn)行增刪查改,本文給大家介紹Go 使用os包操作環(huán)境變量的方法,感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • 詳解Golang如何實(shí)現(xiàn)支持隨機(jī)刪除元素的堆

    詳解Golang如何實(shí)現(xiàn)支持隨機(jī)刪除元素的堆

    堆是一種非常常用的數(shù)據(jù)結(jié)構(gòu),它能夠支持在O(1)的時(shí)間復(fù)雜度獲取到最大值(或最小值)。本文主要介紹了如何實(shí)現(xiàn)支持O(log(n))隨機(jī)刪除元素的堆,需要的可以參考一下
    2022-09-09
  • Golang?中的json.Marshal問題總結(jié)(推薦)

    Golang?中的json.Marshal問題總結(jié)(推薦)

    這篇文章主要介紹了Golang中的json.Marshal問題總結(jié),本文通過一個(gè)例子給大家詳細(xì)講解,本次提出的問題中,我們不難注意到其中的time.Time是一個(gè)匿名(Anonymous)字段,而這個(gè)就是答案的由來,需要的朋友可以參考下
    2022-06-06
  • 詳解Go語言變量作用域

    詳解Go語言變量作用域

    這篇文章主要介紹了Go 語言變量作用域的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用go語言,感興趣的朋友可以了解下
    2021-03-03
  • golang優(yōu)化目錄遍歷的實(shí)現(xiàn)方法

    golang優(yōu)化目錄遍歷的實(shí)現(xiàn)方法

    對于go1.16的新變化,大家印象最深的可能是io包的大規(guī)模重構(gòu),但這個(gè)重構(gòu)實(shí)際上還引進(jìn)了一個(gè)優(yōu)化,這篇文章要說的就是這個(gè)優(yōu)化,所以本將給大家介紹golang是如何優(yōu)化目錄遍歷的,需要的朋友可以參考下
    2024-08-08
  • golang gorm 操作mysql及gorm基本用法

    golang gorm 操作mysql及gorm基本用法

    golang 官方的那個(gè)操作mysql的有點(diǎn)麻煩所以就使用了gorm,下面就gorm的使用做下簡單介紹,感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • 一文詳解Golang如何解決內(nèi)存溢出

    一文詳解Golang如何解決內(nèi)存溢出

    內(nèi)存溢出是指程序在運(yùn)行時(shí)超出了分配給它的內(nèi)存限制,從而導(dǎo)致程序異?;虮罎⒌默F(xiàn)象,本文主要為大家介紹了Golang解決內(nèi)存溢出的方法,感興趣的小伙伴可以了解下
    2025-01-01

最新評論

怀化市| 汶上县| 定边县| 陵川县| 龙川县| 常熟市| 综艺| 清水县| 嵩明县| 库尔勒市| 治多县| 开江县| 建平县| 锦屏县| 金门县| 略阳县| 固阳县| 安陆市| 仪陇县| 福海县| 栖霞市| 梓潼县| 临高县| 米林县| 措美县| 霍林郭勒市| 阿合奇县| 霍林郭勒市| 定结县| 景泰县| 历史| 会东县| 正安县| 孝昌县| 丽水市| 图们市| 包头市| 辽阳市| 余庆县| 新巴尔虎右旗| 阿坝县|