4. 觀察者模式

目錄

  • 一、現實應用場景
  • 二、初步實現
    • 2.1 實現方案1
    • 2.2 實現方案2
  • 三、觀察者模式
    • 3.1 應用場景
    • 3.2 詳解
    • 3.3 實現
    • 3.4 設計類圖
  • 四、實現
  • 五、更多

一、現實應用場景

  1. 教師的手機號改變之后要通知給所有學生
  2. 如果有一個學生沒有通知到位就會產生遺漏
  3. 如何自動完成

二、初步實現

2.1 實現方案1

  • 定義學生和教師類
  • 教師類設置set和get方法
  • 教師的手機號修改后要依次調用所有學生的類重新設置
#include <iostream>class Student
{
private:std::string m_name;std::string m_tPhone;public:Student(const std::string& name){m_name = name;}void setTPhoneNubmer(const std::string& phone){m_tPhone = phone;}void show(){std::cout << "Name: " << m_name << " Teacher's Phone: " << m_tPhone << std::endl;}
};class Teacher
{
private:std::string m_phone;public:Teacher(const std::string& phone){m_phone = phone;}void setPhone(const std::string& phone){m_phone = phone;}std::string getPhone() const {return m_phone;}
};int main()
{Teacher zwz("12345");Student li("LiLei");Student Jie("Jie");Student wcz("wcz");li.setTPhoneNubmer(zwz.getPhone());Jie.setTPhoneNubmer(zwz.getPhone());wcz.setTPhoneNubmer(zwz.getPhone());li.show();Jie.show();wcz.show();//修改zwz.setPhone("67890");li.setTPhoneNubmer(zwz.getPhone());Jie.setTPhoneNubmer(zwz.getPhone());wcz.setTPhoneNubmer(zwz.getPhone());li.show();Jie.show();wcz.show();return 0;
}

2.2 實現方案2

  • 學生類中擁有一個教師的實例,該實例由外部傳入
  • 只要教師的手機號在外部修改,那個學生類中只需要通過getPhone()函數即可得到教師的手機號
  • 實現過程如下
#include <iostream>class Teacher
{
private:std::string m_phone;public:Teacher(const std::string& phone){m_phone = phone;}void setPhone(const std::string& phone){m_phone = phone;}std::string getPhone() const{return m_phone;}
};class Student
{
private:std::string m_name;std::string m_tPhone;const Teacher* m_teacher;public:Student(const std::string& name, const Teacher* teacher){m_name = name;m_teacher = teacher;}void show(){std::cout << "Name: " << m_name << " Teacher's Phone: " << m_teacher->getPhone() << std::endl;}
};int main()
{Teacher zwz("12345");Student li("LiLei", &zwz);Student Jie("Jie", &zwz);Student wcz("wcz", &zwz);li.show();Jie.show();wcz.show();//修改zwz.setPhone("67890");li.show();Jie.show();wcz.show();return 0;
}
  • 存在問題
    • 兩個對象間存在緊耦合關系
    • 如果換老師之后,老師的實例還得修改
    • 缺少擴展性與靈活性

三、觀察者模式

3.1 應用場景

  • 當對象發生變化,通知給其他對象,需要其他對象做出調整
  • 應用程序的可維護性和重用性較高
  • 互動關系不能體現成類之間的直接調用,對象之間關系的解耦

3.2 詳解

  • 觀察者模式又稱為發布訂閱模式
  • 兩個角色: 觀察者和被觀察對象
  • 兩者之間存在”觀察“的邏輯關聯
  • 當被觀察者發生改變的時候,觀察者就會觀察到這樣的變化,并且做出相應的響應
  • 觀察不是直接調用
  • 實現觀察者模式有很多形式,比較直觀的一種是注冊-> 通知 -> 撤銷注冊形式。

3.3 實現

  1. 步驟1:觀察者將自己注冊到被觀察對象中,被觀察對象將觀察者存放在一個容器中。
  2. 步驟2:被觀察者對象發生了某種變化,從容器中得到所有注冊過的觀察者,將變化通知觀察者。
  3. 步驟3(可選):觀察者告訴被觀察者要撤銷觀察,被觀察者從容器中將觀察者去除。

3.4 設計類圖

在這里插入圖片描述

  • ConcreteSubject:
    • 主題對象,被觀察者,對應老師。
    • 他有變化時通知ConcreteObserver類的實例(學生)。學生根據變化自動調用update()做出響應。
    • 內部有一個隊列存儲、移除觀察者
    • 當狀態發生變化時可以調用notifyObservers()通知觀察者
  • ConcreteSubjectConcreteObserver類解耦
    • 學生不只可以觀察老師,還可以觀察學院、某個同學等。
    • 兩個類分別向上抽取了被觀察者接口 (Subject)和觀察者接口(Observer)

四、實現

#include <iostream>
#include <list>class IObserver
{
public:virtual void update(void* o) = 0;
};class ISubject
{
public:virtual void registerObserver(IObserver* obj) = 0;virtual void removeObserver(IObserver* obj) = 0;virtual void notifyObserver() = 0;
};class Teacher: ISubject
{
private:std::string m_phone;std::list<IObserver*> m_subject;public:void setPhone(const std::string& phone){m_phone = phone;notifyObserver();}std::string getPhone() const{return m_phone;}void registerObserver(IObserver* o){m_subject.push_back(o);}void removeObserver(IObserver* o){m_subject.remove(o);}void notifyObserver(){for (auto item : m_subject){item->update((void*)m_phone.c_str());}}
};class Student: public IObserver
{
private:std::string m_name;std::string m_tPhone;public:Student(const std::string& name){m_name = name;}void update(void* o){m_tPhone = reinterpret_cast<char*>(o);}void show(){std::cout << "Name: " << m_name << " Teacher's Phone: " << m_tPhone << std::endl;}
};int main()
{Teacher zwz;Student li("LiLei");Student Jie("Jie");Student wcz("wcz");Student test("test");zwz.registerObserver(&li);zwz.registerObserver(&Jie);zwz.registerObserver(&wcz);std::cout << "\n*******設置教師手機號為12345*******" << std::endl;zwz.setPhone("12345");li.show();Jie.show();wcz.show();zwz.removeObserver(&wcz); //移除對wcz的通知std::cout << "\n*******對教師手機號進行修改為67890*******" << std::endl;//修改zwz.setPhone("67890");li.show();Jie.show();std::cout << "\n*******不會被改變*******" << std::endl;wcz.show();  //不會被改變return 0;
}
  • 創建觀察者接口IObserver(),并規定了更新的行為。
  • 創建被觀察者接口ISubject(),并規定了添加、移除和通知觀察者的行為。
  • 運行結果
    在這里插入圖片描述

五、更多

  • 這個例子中需要在main函數中手動調用注冊,可以在Observer對象創建時傳入Subject對象,以便自動注冊。
  • 詳情請參閱 https://gitee.com/piglittle/design_patterns中的 Head_First_Design_Partterns解決方案下的 observer_pattern項目
  • 其詳細的類圖如下
    請添加圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/91327.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/91327.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/91327.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

es 啟動中的一些記錄

完整修復流程 bash # 1. 創建用戶主目錄(如果需要) mkdir -p /home/es8 chown es8:es8 /home/es8# 2. 變更 Elasticsearch 目錄所有權 chown -R es8:es8 /data/es/elasticsearch-8.17.2/# 3. 調整目錄和文件權限 chmod -R 755 /data/es/elasticsearch-8.17.2/ chmod 644 /d…

區塊鏈之拜占庭容錯算法——Practical Byzantine Fault Tolerance(PBFT)

實用拜占庭容錯算法&#xff08;PBFT&#xff09;是由 Barbara Liskov 和 Miguel Castro 于 90 年代末提出的一種共識算法。原論文鏈接如下&#xff1a; http://pmg.csail.mit.edu/papers/osdi99.pdf pBFT 被設計為在異步&#xff08;響應請求的時間沒有上限&#xff09;系統…

從電子管到CPU

在線verilog轉電路圖 簡單門電路 https://logic.ly/demo/ 數學基礎 普通邏輯 與自然語言關系緊密, 亞里士多德三段論,??穆勒五法 , 語言, 語義,概念,定義,辯論, 詐騙 等, 是文科類的邏輯。 離散數學 不連續數學 數理邏輯 命題邏輯與謂詞邏輯, 與數學推理關系緊密, 它…

Javase-8.數組的練習

1.查找數組中指定元素(二分查找)以升序數組為例, 二分查找的思路是先取中間位置的元素, 然后使用待查找元素與數組中間元素進行比較&#xff1a; 如果相等&#xff0c;即找到了返回該元素在數組中的下標 如果小于&#xff0c;以類似方式到數組左半側查找 如果大于&#xff0c;以…

H3CNE綜合實驗之機器人

H3CNE綜合實驗之機器人 實驗拓撲圖實驗需求 1.按照圖示配置 IP 地址 2.SW1 和 SW2 之間的直連鏈路配置鏈路聚合 3.公司內部業務網段為 Vlan10 和 Vlan20;Vlan10 是市場部&#xff0c;Vlan20 是技術部&#xff0c;要求對 Vlan 進行命名以識別; ? PC8 屬于 Vlan10&#xff0c…

2025/7/15——java學習總結

Java IO、Stream、異常與 File 全體系總結&#xff1a;從基礎到進階的完整突破一、核心知識深耕&#xff1a;四大模塊的體系與底層邏輯&#xff08;一&#xff09;IO 流&#xff1a;數據傳輸的基礎通道體系架構與核心分類按流向&#xff1a;輸入流&#xff08;InputStream/Read…

【軌物方案】當補貼退潮,光伏電站如何回歸價值本質?

中國光伏產業正站在一個歷史性的拐點。過去&#xff0c;國家補貼的“黃金時代”催生了裝機量的爆發式增長&#xff0c;許多電站在建設初期將重心放在了快速并網&#xff0c;卻忽視了貫穿2-30年生命周期的運維規劃。如今&#xff0c;補貼浪潮逐漸退去&#xff0c;各大企業開始從…

群暉Nas - Docker(ContainerManager)上安裝SVN Server和庫權限設置問題

上次安裝了Gitlab&#xff0c;可以參考這篇&#xff08;群暉Nas - Docker&#xff08;ContainerManager&#xff09;上安裝GitLab&#xff09;&#xff0c;今天來搞SVN服務器&#xff0c;廢話不多說。 下載鏡像 還是先下載鏡像&#xff08;garethflowers/svn-server&#xff…

前端打包自動壓縮為zip--archiver

安裝依賴 pnpm add archiver types/archiver/vitePlugins/autoBuildZip.ts import { Plugin } from vite; import archiver from archiver; import fs from fs;const compressFolder (folderPath: string, outputFilePath: string) > {const output fs.createWriteStream(…

React響應式組件范式:從類組件到Hooks

?引言 在UI開發中&#xff0c;"狀態變化自動觸發UI更新"的響應式機制是構建動態界面的核心。React通過獨特的??單向數據流??和??虛擬DOM&#xff08;Virtual DOM&#xff09;?? 實現這一目標&#xff0c;但類組件&#xff08;Class Components&#xff09;…

com2tcp工具

com2tcp 是 com0com 套件中的一個實用工具&#xff0c;用于將本地串口&#xff08;COM&#xff09;數據轉發到 TCP/IP 網絡&#xff0c;或者將 TCP/IP 數據轉發到本地串口&#xff0c;實現串口數據的網絡透傳。 1. com2tcp 基本用法 &#xff08;1&#xff09;安裝 com0com 從…

MySQL實操:將Word表格數據導入MySQL表

文章目錄 1. 提出任務1.1 Word表格數據1.2 查看商品空表1.3 任務要求2. 完成任務2.1 借助AI2.1.1 利用AI生成SQL語句2.1.2 在Navicat里執行查詢2.1.3 查看商品表記錄2.2 借助Excel2.2.1 將Word表格數據復制到Excel2.2.2 新建商品表2.2.3 利用導入向導將電子表格數據導入商品表2…

什么是Podman?能否替代Docker?Podman快速入門

什么是PodmanPodman&#xff08;POD Manager&#xff09;是一個開源的無守護進程&#xff08;daemonless&#xff09;容器引擎&#xff0c;用于管理容器、容器鏡像、容器卷和網絡。它兼容 OCI 標準&#xff0c;可以運行 Docker 鏡像&#xff0c;并且設計上與 Docker CLI 命令高…

開通保存圖片權限

直接粘貼就可以用 上干貨 可以的話希望點個start/* 小程序特有相關 */mp-weixin: {appid: VITE_WX_APPID,setting: {urlCheck: false,minified : true //是否壓縮js},usingComponents: true,"lazyCodeLoading": "requiredComponents", //按需注入"pe…

【趙渝強老師】大數據交換引擎Sqoop

Sqoop是SQL To Hadoop的簡稱&#xff0c;它是一款開源的工具&#xff0c;主要用于在Hadoop&#xff08;Hive&#xff09;與傳統的數據庫&#xff08;Oracle、MySQL等&#xff09;間進行數據的傳遞。通過使用Sqoop可以將一個關系型數據庫中的數據導進到Hadoop的HDFS中&#xff0…

C++進階-map的應用

目錄 1.預備知識 2.map的補充知識 2.1map的插入方式 2.2訪問鍵和值 2.3map::operator[]的補充 2.4另外一些map的成員函數的補充 3.map的應用實踐-力扣刷題-前k個高頻單詞 3.1解法1 3.2解法2 3.3解法3 4.map的應用實踐-力扣刷題-隨機鏈表的復制 4.1C語言解法 4.2C解…

【三維重建工具】NeRFStudio、3D GaussianSplatting、Colmap安裝與使用指南

目錄 一、NeRFStudio安裝1.安裝&#xff08;ubuntu系統&#xff09;2.安裝&#xff08;windows系統&#xff09; 二、安裝tinycudann三、Colmap安裝與使用1. 安裝依賴2. 安裝colmap3.使用colmap3.1 可視化界面使用3.2 Nerfstudio命令行調用Colmap3.3 colmap結果不準時的修復3.4…

Mybatis05-動態sql

一、應用場景MyBatis 的 動態 SQL 是指根據不同的條件動態拼接生成 SQL 語句的能力。它的最大優勢是&#xff1a;避免寫多個 XML 映射語句、避免 SQL 冗余、提升代碼復用性和可維護性。示例1&#xff1a;用戶可以通過勾選框&#xff0c;勾選不同的數據進行批量刪除&#xff0c;…

VSCODE 選中多行 需要同時按住alt鍵才可以

在 VS Code 中&#xff0c;如果你發現 必須按住 Alt 鍵才能選中多行&#xff08;即“列選擇”或“塊選擇”模式&#xff09;&#xff0c;而直接拖動鼠標無法多選&#xff0c;可能是由于以下原因導致的&#xff1a;1. 檢查是否啟用了“列選擇模式”VS Code 默認情況下&#xff1…

2025前端面試真題以及答案-不斷整理中,問題來源于牛客真題

一、 項目內存泄露react與vue的渲染機制有哪些不同react fiber架構vue2與3&#xff0c;為什么用proxy代替defineproperty性能優化有哪些三欄布局實現方式重排與重繪一個對話聊天框如何減少重排&#xff08;我回答的是絕對定位&#xff0c;將聊天框定位在下面&#xff0c;類似于…