【設計模式】observer(觀察者)-- 對象行為型模式5.7

来源:http://www.cnblogs.com/vanishfan/archive/2017/04/19/6728120.html
-Advertisement-
Play Games

1.意圖 對象之間一對多的依賴關係,當目標對象發生改變時,所有依賴於它的對象都要得到通知並自動更新 2.別名 依賴,發佈-訂閱 3.動機 1)需要確保相互協作的對象的一致性(數據要保持一致),但一致性會使各個對象緊密耦合,減低它們的可重用性。 2)Observer模式描述瞭如何建立這種關係:一個目標 ...


1.意圖

對象之間一對多的依賴關係,當目標對象發生改變時,所有依賴於它的對象都要得到通知並自動更新

2.別名

依賴,發佈-訂閱

3.動機

1)需要確保相互協作的對象的一致性(數據要保持一致),但一致性會使各個對象緊密耦合,減低它們的可重用性。

2)Observer模式描述瞭如何建立這種關係:一個目標(Subject)可以有任意個依賴於它的觀察者(Observer),當目標發生改變的時候,所有觀察者都得到通知(Notify);觀察者響應通知(Update),會去查詢目標狀態(GetState)使其狀態與目標狀態同步一致。

3)觀察者去訂閱(Subscribe),目標去發佈(Publish)

4.適用性

1)一個抽象模型有兩方面,一方面依賴於另一方面,兩者獨立封裝在不同對象里以方便各自獨立的改變和復用

2)一個對象的改變需要通知另一個對象,而被通知的對象數量不確定

3)被通知的對象之間互相不知道對方是誰,沒有緊密耦合

5.結構 & 6.參與者

 

7.協作

8.效果

1)目標與觀察者之間的抽象耦合:目標不知道具體觀察者是屬於哪個類的,只知道他們符合抽象Subject的介面,具體目標本身也可以是各式各樣的,只要符合Object抽象介面即可,所以耦合是抽象和最小的,目標和觀察者可以屬於整個系統中的任意一個層次。

2)支持廣播通信:目標可以無腦廣播給所有它的觀察者,不用知道觀察者是誰,是否響應處理通知可以放在觀察者層去判斷

3)意外的更新:A觀察者不知道B觀察者的存在,A的操作導致目標改變,會通知到B,若B其實不依賴目標(定義了錯誤的依賴關係)可能會導致大量無效的通知或者通知導致B觀察者數據錯誤

9.實現

1)創建目標與觀察者之間的映射

  方法1:在目標裡面存放觀察者列表,簡單,但目標多觀察者少的時候存儲代價會高一些

  方法2:用一個公共的對象來存儲subjects 和 observers之間的映射

2)觀察多個目標

  Update裡面傳參數Subject,來告知觀察者是哪個目標更新

3)誰觸發更新

  方式1:目標對象的屬性變更時由目標觸發更新通知,好處觀察者和其他對象不用關心何時觸發更新不會出現遺漏,缺點是一個操作可能會導致多次更新,也會發多次通知

  方式2:由客戶來觸發更新通知,好處可以隨時控制觸發更新時機,避免中間更新,缺點會遺漏觸發

4)對已刪除目標的懸掛引用

  通知目標的所有觀察者把目標從身上的引用移除

5)在發出通知前確保目標的狀態自身是一致的

  方式1:Subject上的Notify在SetState之後調用,因為Observer裡面的Update可能會從Subject上GetState

  方式2:用Template Method模式,即父類Subject中的模板方法把重定義操作Operation()放在Notify()之前,子類只要重定義Operation方法即可,就能確保操作完了才Notify

6)通知模型 推/拉

  push推模型:把詳細信息都通知給所有觀察者,不管他們是否需要;推模型假定知道觀察者需要什麼,但假定不一定正確可能使得觀察者難以復用(收到了大量無用信息,自己想要的又沒有推送)

  pull拉模型只發送最小通知(如告訴觀察者有更新了),觀察根據自己需要從目標取他想要的數據;拉模型假定目標不知道觀察者,但效率會低,因為在目標發送信息太少的情況下觀察者無法知道目標到底改變了什麼

7)顯式的指定關心內容

  void Subject::Attach(Observer *, Aspect& interest);  觀察者註冊時指定關心的目標方面變更,目標只通知關心改變方面的觀察者,併在Update里把Subject和Aspect都帶上

  這個操作在Observer端做篩選其實也行。

8)封裝複雜的更新語義

  更新管理器ChangeManager的職責,是個Mediator,Singleton

  a) 它將一個目標映射到它的觀察者並提供一個介面來維護這個映射。這就不需要由目標來維護對其觀察者的引用, 反之亦然。

  b) 它定義一個特定的更新策略。(比如N個目標都改變了才觸發通知,或者目標在400ms發生改變只觸發一次)

  c) 根據一個目標的請求, 它更新所有依賴於這個目標的觀察者。

 

9)結合目標類和觀察者類

  兩者可以放到一個類里

10.日常開發項目應用

1)跨服邏輯,gameserver是觀察者,centerserver是目標;gameserver連上後會Attach到centerserver,斷開就Detach, centerserver上的globalserver列表發生更新的時候需要Notify所有的gameserver,用於更新PK服列表信息

2)戰鬥邏輯,player是觀察者,player和monster是目標entity;entity進入player可視範圍Attach,離開Detach,entity移動後坐標發生變更,需要通知他周圍的觀察者player坐標變更,這裡使用了ChangeManager(map)來管理這個依賴關係的映射,並且制定了更新策略:發生變更不立馬通知,400ms tick的時候如果有變更則通知觀察者


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在進入mvc5之後,OWIN變更很主推,很熱,關於OWIN的文章也就出來了,下麵閱讀了dudu和一些園友的文章,自己也做了一個SelfHost的程式,測試了一下,感覺還是比較有Core的風格,可能也是面向多平臺部署考慮的吧! OWIN的英文全稱是Open Web Interface for .NET ...
  • 結合模板和巨集定義,可以很方便的單例化任何類 ...
  • UML:統一建模語言由OMG(Object Management Group)在1997年發表的圖標式軟體設計語言,它綜合了很多當時已經存在的面向對象的建模語言、方法和過程。 UML語言具有以下的重要功能:可視化(Visualizing)功能、說明(Specifying)功能、建造(Construc ...
  • Web Service 首發於 "開源中國" 1. 背景 中國移動簡訊網關需求,要能夠發送簡訊。開發材料只有一個簡訊發送配置:包括ID,password,code,url。一個jar包還有一個老舊的html幫助文檔。 最初將單個jar包加入工程,按照文檔中new 一個對象,直接填入參數發送的來,以為 ...
  • 當要把類替換成不同子類的時候不需要改調用的代碼,只需修改工廠類。例子: 資料庫連接類,當把mysql改成其他資料庫的時候,不用修改調用的地方。 ...
  • 重載 overload //函數重載 編譯多態 /*public void Test(string s) 第一個函數 (字元串類型) { echo "1111"; } public void Test(int a) 第二個函數(整數型,與第一個函數類型不同) { echo "int"; } publ ...
  • 自動裝配 @Resource註解需要提供bean名字,若為空,自動採用標簽下變數名或者方法名為bean的名稱。 @Inject和@AutoWired都是自動裝配,不過前者沒有reqired屬性,建議使用後者。 @Required註解主要用於setter方法之上,在bean中明確指定自動註入值或其屬性 ...
  • 原因:之前修改代碼看心情和工作量。後來接觸了一個小項目的重構工作,發現自己並沒有系統的重構邏輯。所以覺得有必要 去學習一下。所以選擇了上面說的兩本書。以下作為自己看書的領悟和記錄。 首先:為什麼重構? 首先改善代碼易讀性,包括機器和人。 機器易讀性:提高性能,減少冗餘,分類清楚,保持健壯性的前提下盡 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...