《C++新經典設計模式》之第17章 中介者模式

《C++新經典設計模式》之第17章 中介者模式

        • 中介者模式.cpp

中介者模式.cpp
#include <iostream>
#include <map>
#include <memory>
using namespace std;// 中介者封裝一系列的對象交互
// 4種角色
// Mediator(抽象中介者類),定義接口,各個同事類通過該接口與中介者通信
// ConcreteMediator(具體中介者類),實現接口,保存同事類指針用于與同事對象通信實現協作行為
// Colleague(抽象同事類),定義同事共有方法和抽象方法,同時維持中介者對象指針用于通信
// ConcreteColleague(具體同事類),實現方法
// 可結合觀察者模式,即中介者實現為觀察者,各個同事類實現為觀察目標namespace ns1
{class CtlParent // UI控件類{protected:string m_caption; // 控件上面顯示的文字內容,本范例假設每個UI控件上的文字都不同public:virtual ~CtlParent() {}CtlParent(const string &caption) : m_caption(caption) {}public:                                                                         // 當UI控件發生變化時該成員函數會被調用virtual void Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist) = 0; // 形參所代表的map容器中包含著所有對話框中涉及到的UI控件virtual void Enable(bool sign) const = 0;                                   // 設置UI控件啟用或禁用};class Button : public CtlParent // 普通按鈕相關類{public:Button(const string &caption) : CtlParent(caption) {}public:void Enable(bool sign) const override // 設置按鈕的啟用或禁用{if (sign)cout << "button \"" << m_caption << "\" enable" << endl;elsecout << "button \"" << m_caption << "\" disable" << endl;}// 按鈕被按下時該成員函數會被調用void Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist) override;};class RadioBtn : public CtlParent // 單選按鈕相關類{public:RadioBtn(const string &caption) : CtlParent(caption) {}public:void Enable(bool sign) const override {} // 設置單選按鈕的啟用或禁用// 設置單選按鈕為被選中或者被取消選中,被選中的單選按鈕中間有個黑色實心圓點void Selected(bool sign) const{if (sign)cout << "radio button \"" << m_caption << "\" selected" << endl;elsecout << "radio button \"" << m_caption << "\" not selected" << endl;}// 單選按鈕被單擊時該成員函數會被調用void Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist) override;};class EditCtl : public CtlParent // 編輯框相關類{string m_content = ""; // 編輯框中的內容public:EditCtl(const string &caption) : CtlParent(caption) {}public:void Enable(bool sign) const override // 設置編輯框的啟用或禁用{if (sign)cout << "edit box \"" << m_caption << "\" enable" << endl;elsecout << "edit box \"" << m_caption << "\" disable" << endl;}// 是否編輯框中的內容為空bool isContentEmpty() const { return m_content.empty(); }// 編輯框內容發生變化時該成員函數會被調用void Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist) override;};// 按鈕被按下時該成員函數會被調用void Button::Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist){if (m_caption == "sign in") // 按下的是登錄按鈕cout << "Start the game login verification, and decide whether to enter the game or give a prompt according to the verification result!" << endl;else if (m_caption == "exit") // 按下的是退出按鈕,則退出整個游戲cout << "Game exit, goodbye!" << endl;}// 單選按鈕被單擊時該成員函數會被調用void RadioBtn::Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist){if (m_caption == "visitor login"){static_pointer_cast<RadioBtn>(tmpuictllist["visitor login"])->Selected(true);  // “游客登錄”單選按鈕設置為選中static_pointer_cast<RadioBtn>(tmpuictllist["account login"])->Selected(false); // “賬號登錄”單選按鈕設置為取消選中tmpuictllist["account"]->Enable(false);  // “賬號”編輯框設置為禁用tmpuictllist["password"]->Enable(false); // “密碼”編輯框設置為禁用tmpuictllist["sign in"]->Enable(true); // “登錄”按鈕設置為啟用}else if (m_caption == "account login"){static_pointer_cast<RadioBtn>(tmpuictllist["visitor login"])->Selected(false); // “游客登錄”單選按鈕設置為取消選中static_pointer_cast<RadioBtn>(tmpuictllist["account login"])->Selected(true);  // “賬號登錄”單選按鈕設置為選中tmpuictllist["account"]->Enable(true);  // “賬號”編輯框設置為啟用tmpuictllist["password"]->Enable(true); // “密碼”編輯框設置為啟用// 如果“賬號”編輯框或者“密碼”編輯框有一個為空,則不允許登錄if (static_pointer_cast<EditCtl>(tmpuictllist["account"])->isContentEmpty() || static_pointer_cast<EditCtl>(tmpuictllist["password"])->isContentEmpty())tmpuictllist["sign in"]->Enable(false); // “登錄”按鈕設置為禁用elsetmpuictllist["sign in"]->Enable(true); // “登錄”按鈕設置為啟用}}// 編輯框內容發生變化時該成員函數會被調用void EditCtl::Changed(map<string, shared_ptr<CtlParent>> &tmpuictllist){// 如果“賬號”編輯框或者“密碼”編輯框有一個為空,則不允許登錄if (static_pointer_cast<EditCtl>(tmpuictllist["account"])->isContentEmpty() || static_pointer_cast<EditCtl>(tmpuictllist["password"])->isContentEmpty())tmpuictllist["sign in"]->Enable(false); // “登錄”按鈕設置為禁用elsetmpuictllist["sign in"]->Enable(true); // “登錄”按鈕設置為啟用}
}namespace ns2
{class CtlParent; // 類前向聲明class Mediator   // 中介者父類{public:virtual ~Mediator() {}public:virtual void createCtrl() = 0;                 // 創建所有需要用到的UI控件virtual void ctlChanged(CtlParent *const) = 0; // 當某個UI控件發生變化時調用中介者對象的該成員函數來通知中介者};class CtlParent // UI控件類的父類{protected:Mediator *m_pmediator; // 指向中介者對象的指針string m_caption;      // 控件上面顯示的文字內容,可能并不是所有控件都需要但這里為顯示方便依舊引入public:virtual ~CtlParent() {}CtlParent(Mediator *const ptmpm, const string &caption) : m_pmediator(ptmpm), m_caption(caption) {}public:                                                       // 當UI控件發生變化時該成員函數會被調用virtual void Changed() { m_pmediator->ctlChanged(this); } // 通知中介者對象,所有事情讓中介者對象去做virtual void Enable(bool sign) = 0;                       // 設置UI控件啟用或禁用};class Button : public CtlParent // 普通按鈕相關類{public:Button(Mediator *const ptmpm, const string &caption) : CtlParent(ptmpm, caption) {}void Enable(bool sign) override // 設置按鈕的啟用或禁用{if (sign == true)cout << "button \"" << m_caption << "\" enable" << endl;elsecout << "button \"" << m_caption << "\" disable" << endl;}};class RadioBtn : public CtlParent // 單選按鈕相關類{public:RadioBtn(Mediator *const ptmpm, const string &caption) : CtlParent(ptmpm, caption) {}void Enable(bool sign) override {} // 設置單選按鈕的啟用或禁用void Selected(bool sign)           // 設置單選按鈕為被選中或者被取消選中,被選中的單選按鈕中間有個黑色實心圓點{if (sign == true)cout << "radio button \"" << m_caption << "\" selected" << endl;elsecout << "radio button \"" << m_caption << "\" not selected" << endl;}};class EditCtl : public CtlParent // 編輯框相關類{string m_content = ""; // 編輯框中的內容public:EditCtl(Mediator *const ptmpm, const string &caption) : CtlParent(ptmpm, caption) {}void Enable(bool sign) override // 設置編輯框的啟用或禁用{if (sign == true)cout << "edit box \"" << m_caption << "\" enable" << endl;elsecout << "edit box \"" << m_caption << "\" disable" << endl;}bool isContentEmpty() const { return m_content.empty(); } // 是否編輯框中的內容為空};class concrMediator : public Mediator // 具體中介者類{public:                           // 為方便外界使用,這里以public修飾,實際項目中可以寫一個成員函數來return這些指針shared_ptr<Button> mp_login;  // 登錄按鈕shared_ptr<Button> mp_logout; // 退出按鈕shared_ptr<RadioBtn> mp_rbtn1; // 游客登錄單選按鈕shared_ptr<RadioBtn> mp_rbtn2; // 賬號登錄單選按鈕shared_ptr<EditCtl> mp_edtctl1; // 賬號編輯框shared_ptr<EditCtl> mp_edtctl2; // 密碼編輯框public:void createCtrl() override // 創建各種UI控件{// 當然,各種UI控件對象在外面創建,然后把地址傳遞進來也可以mp_login = make_shared<Button>(this, "sign in");mp_logout = make_shared<Button>(this, "exit");mp_rbtn1 = make_shared<RadioBtn>(this, "visitor login");mp_rbtn2 = make_shared<RadioBtn>(this, "account login");mp_edtctl1 = make_shared<EditCtl>(this, "account editing box");mp_edtctl2 = make_shared<EditCtl>(this, "password editing box");// 設置一下缺省的UI控件狀態mp_rbtn1->Selected(true);  // “游客登錄”單選按鈕設置為選中mp_rbtn2->Selected(false); // “賬號登錄”單選按鈕設置為取消選中mp_edtctl1->Enable(false); // “賬號”編輯框設置為禁用mp_edtctl2->Enable(false); // “密碼”編輯框設置為禁用mp_login->Enable(true);  // “登錄”按鈕設置為啟用mp_logout->Enable(true); // “退出”按鈕設置為啟用}// 當某個UI控件發生變化時調用中介者對象的該成員函數來通知中介者virtual void ctlChanged(CtlParent *const p_ctrl){if (p_ctrl == mp_login.get()) // 登錄按鈕被單擊cout << "Start the game login verification, and decide whether to enter the game or give a prompt according to the verification result!" << endl;else if (p_ctrl == mp_logout.get())        // 退出按鈕被單擊cout << "Game exit, goodbye!" << endl; // 退出整個游戲if (p_ctrl == mp_rbtn1.get()) // 游客登錄單選按鈕被單擊{mp_rbtn1->Selected(true);  // “游客登錄”單選按鈕設置為選中mp_rbtn2->Selected(false); // “賬號登錄”單選按鈕設置為取消選中mp_edtctl1->Enable(false); // “賬號”編輯框設置為禁用mp_edtctl2->Enable(false); // “密碼”編輯框設置為禁用mp_login->Enable(true); // “登錄”按鈕設置為啟用}else if (p_ctrl == mp_rbtn2.get()) // 賬號登錄單選按鈕被單擊{mp_rbtn1->Selected(false); // “游客登錄”單選按鈕設置為取消選中mp_rbtn2->Selected(true);  // “賬號登錄”單選按鈕設置為選中mp_edtctl1->Enable(true); // “賬號”編輯框設置為啟用mp_edtctl2->Enable(true); // “密碼”編輯框設置為啟用if (mp_edtctl1->isContentEmpty() || mp_edtctl2->isContentEmpty()) // 如果“賬號”編輯框或者“密碼”編輯框有一個為空,則不允許登錄mp_login->Enable(false);                                      // “登錄”按鈕設置為禁用elsemp_login->Enable(true); // “登錄”按鈕設置為啟用}if (p_ctrl == mp_edtctl1.get() || p_ctrl == mp_edtctl2.get())         // 賬號或密碼編輯框內容發生改變if (mp_edtctl1->isContentEmpty() || mp_edtctl2->isContentEmpty()) // 如果“賬號”編輯框或者“密碼”編輯框有一個為空,則不允許登錄mp_login->Enable(false);                                      // “登錄”按鈕設置為禁用elsemp_login->Enable(true); // “登錄”按鈕設置為啟用}};
}int main()
{
#if 0using namespace ns1;// 創建各種UI控件map<string, shared_ptr<CtlParent>> uictllist; // 將所有創建的UI控件保存到map容器中,方便進行參數傳遞uictllist["sign in"] = make_shared<Button>("sign in");uictllist["exit"] = make_shared<Button>("exit");uictllist["visitor login"] = make_shared<RadioBtn>("visitor login");uictllist["account login"] = make_shared<RadioBtn>("account login");uictllist["account"] = make_shared<EditCtl>("account");uictllist["password"] = make_shared<EditCtl>("password");// 設置一下缺省的UI控件狀態// 因為只有子類型才有Selected成員函數,所以這里需要用到強制類型轉換static_pointer_cast<RadioBtn>(uictllist["visitor login"])->Selected(true);  // “游客登錄”單選按鈕設置為選中static_pointer_cast<RadioBtn>(uictllist["account login"])->Selected(false); // “賬號登錄”單選按鈕設置為取消選中uictllist["account"]->Enable(false);  // “賬號”編輯框設置為禁用uictllist["password"]->Enable(false); // “密碼”編輯框設置為禁用uictllist["sign in"]->Enable(true); // “登錄”按鈕設置為啟用uictllist["exit"]->Enable(true);    // “退出”按鈕設置為啟用cout << "--------------------------" << endl;uictllist["account login"]->Changed(uictllist); // 模擬“賬號登錄”單選按鈕被單擊選中
#endif#if 1using namespace ns2;concrMediator mymedia;mymedia.createCtrl();cout << "-------------when \"account login\" radio button pressed:-------------" << endl;// 模擬“賬號”按鈕被按下,則去通知中介者,由中介者實現具體的邏輯處理mymedia.mp_rbtn2->Changed();
#endifcout << "Over!\n";return 0;
}

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

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

相關文章

MYSQL練題筆記-高級查詢和連接-指定日期的產品價格

這依舊是中等題&#xff0c;想了好久&#xff0c;終于理解了很開心&#xff01; 一、題目相關內容 1&#xff09;相關的表和題目 2&#xff09;幫助理解題目的示例&#xff0c;提供返回結果的格式 二、自己初步的理解 題目是找出2019-08-16 時全部產品的價格&#xff0c;所以…

數字化時代的到來,IT運維產業正在發生深刻的變革

IT運維產業是隨著信息技術的發展而產生的&#xff0c;它涵蓋了從硬件到軟件、從應用到數據、從終端到云端等各個方面的維護和管理。隨著數字化時代的到來&#xff0c;IT運維產業正在發生深刻的變革。其中&#xff0c;大數據技術的廣泛應用和數據資源的日益豐富&#xff0c;正在…

使用最小花費爬樓梯

1.狀態表示 2.狀態轉移方程 3.初始化 保證填表時&#xff0c; 不越界 4.填表順序 從左往右 5.返回值 解法2&#xff1a; 1.狀態表示 2.狀態轉移方程 3.初始化 4.填表 從右往左 5.返回值 min( dp[0] , dp[1] ) ----------------------------------------------------…

java+springboot+ssm學生社團管理系統76c2e

本系統包括前臺和后臺兩個部分。前臺主要是展示社團列表、社團風采、社團活動、新聞列表等&#xff0c;前臺登錄后進入個人中心&#xff0c;在個人中心能申請加入社團、查看參加的社團活動等&#xff1b;后臺為管理員與社團負責人使用&#xff0c;應用于對社團的管理及內容發布…

Vue3源碼梳理:源碼目錄結構及源碼閱讀方法

VUE3 源碼目錄結構 1 ) 下載源碼三種方式 方式1&#xff0c;Download ZIP&#xff0c;不推薦方式2&#xff0c;通過https,或ssh或github cli來克隆項目 $ git clone https://github.com/vuejs/core.git$ git clone gitgithub.com:vuejs/core.git 方式3&#xff0c;點擊Fork, …

常見統計學習方法特點總結

1. 概述 方法適用問題模型特點模型類型學習策略損失函數學習算法1感知機二分類分離超平面判別模型極小化誤分點到超平面距離誤分點到超平面距離SGD2KNN多分類&#xff0c;回歸特征空間&#xff0c;樣本點判別模型---3樸素貝葉斯多分類特征與類別的聯合概率分布&#xff0c;條件…

【CMU 15-445】Proj2 Hash Index

EXTENDIBLE HASH INDEX 通關記錄Task1 Read/Write Page Guards移動構造函數Drop方法移動賦值運算符析構函數UpgradeRead函數FetchPageBasic、FetchPageRead、FetchPageWrite、NewPageGuarded Task2 Extendible Hash Table PagesHeaderPageDirectoryPageBucketPage Task3 Extend…

飛天使-linux操作的一些技巧與知識點5

文章目錄 roles批量替換文件 role 的依賴關系role 的實際案例 roles tasks 和 handlers &#xff0c;那怎樣組織 playbook 才是最好的方式呢&#xff1f;簡 單的回答就是&#xff1a;使用 Roles Roles 基于一個已知的文件結構&#xff0c;去自動的加載 vars&#xff0c;tasks 以…

Python字典去重竟然比集合去重快速40多倍

這里寫目錄標題 對比代碼結果圖代碼解析 對比代碼 from glob import glob from tqdm import tqdm import time path_listglob("E:/sky_150b/任務組_20231207_2023/*.jsonl") # for two in tqdm(path_list): onepath_list[0]with open(one,"r",encoding&q…

【C++】POCO學習總結(十):Poco::Util::Application(應用程序框架)

【C】郭老二博文之&#xff1a;C目錄 1、Poco::Util::Application 應用框架 1.1 應用程序基本功能 Poco::Util::Application是POCO實現的的應用程序框架&#xff0c;支持功能如下&#xff1a; 命令行參數處理配置文件初始化和關機日志 1.2 命令行程序和守護進程 POCO支持…

Java架構師系統架構實現高內聚低耦合

目錄 1 導語2 邊界內聚耦合概述3 聚焦內聚4 關注耦合5 如何實現高內聚低耦合6 內聚耦合規劃不當的效果7 總結想學習架構師構建流程請跳轉:Java架構師系統架構設計 1 導語 架構設計的核心維度,從系統的擴展性、高性能、高可用、高安全性和伸縮性五個維度進行了探討,并介紹了…

【Docker】進階之路:(一)容器技術發展史

【Docker】進階之路&#xff1a;&#xff08;一&#xff09;容器技術發展史 什么是容器為什么需要容器容器技術的發展歷程Docker容器是如何工作的 什么是容器 容器作為一種先進的虛擬化技術&#xff0c;已然成為了云原生時代軟件開發和運維的標準基礎設施。在了解容器技術之前…

抖音本地生活服務商申請入口在哪里?具體流程是怎樣的?

不論是抖音的本地生活業務&#xff0c;還是后來的支付寶、視頻號的本地生活業務&#xff0c;因為市場體量足夠龐大&#xff0c;市場前景廣闊&#xff0c;一直很受各大創業者的追捧。那么&#xff0c;如此火熱的本地生活項目&#xff0c;想要申請成為服務商&#xff0c;具體的申…

列表標簽的介紹與使用

列表的作用&#xff1a; 整齊、整潔、有序&#xff0c;它作為布局會更加自由和方便。 根據使用情景不同&#xff0c;列表可以分為三大類&#xff1a;無序列表、有序列表和自定義列表 無序列表 <ul> 標簽表示 HTML 頁面中項目的無序列表&#xff0c;一般會以項目符號呈…

深入了解linux下網卡防火墻selinux

深入了解linux下網卡防火墻selinux 在Linux系統中&#xff0c;網絡安全是非常重要的。為了保護系統免受惡意攻擊和未經授權的訪問&#xff0c;我們可以使用防火墻來限制網絡流量。而在Linux下&#xff0c;我們可以使用SELinux&#xff08;Security-Enhanced Linux&#xff09;…

Java調試技巧之垃圾回收機制解析

Java作為一種高級編程語言&#xff0c;以其跨平臺、面向對象、自動內存管理等特性而廣受開發者的喜愛。其中&#xff0c;自動內存管理是Java的一大亮點&#xff0c;通過垃圾回收機制實現對內存的自動分配和釋放&#xff0c;極大地簡化了開發者的工作。本文將深入探討Java的垃圾…

mysql數據庫文件丟失恢復---惜分飛

客戶服務器重啟,mysql相關數據文件丟失 通過底層工具進行分析,無法正確恢復數據庫名字,一個個單個ibd文件(而且很多本身是錯誤的) 對于這種情況,通過mysql block掃描恢復出來page文件 恢復出來客戶需要數據 這個客戶出現該故障的原因大概率是由于文件系統損壞導致.最終…

C語言進階之路-數據結構篇

目錄 一、學習目標 二、數據結構 1.基本概念 線性關系&#xff1a; 非線性關系&#xff1a; 存儲形式 2. 算法分析 2.1 時間復雜度 2.2 空間復雜度 2.3 時空復雜度互換 總結 一、學習目標 了解數據結構的基本概念了解算法的分析方法 二、數據結構 1.基本概念 數據結…

測試bug分析

項目場景&#xff1a; 提示&#xff1a;這里簡述項目相關背景&#xff1a; 例如&#xff1a;項目場景&#xff1a;示例:通過藍牙芯片(HC-05)與手機 APP 通信&#xff0c;每隔 5s 傳輸一批傳感器數據(不是很大) 問題描述 提示&#xff1a;這里描述項目中遇到的問題&#xff1…

Nacos源碼解讀11——客戶端怎么讀取最新的配置信息

項目啟動怎么讀取的配置信息 自動裝配 SpringBoot 自動裝配機制 加載 WEB/INF spring.factories 會將如下幾個Bean加載到ioc 容器中 BeanConditionalOnMissingBeanpublic NacosConfigProperties nacosConfigProperties() {return new NacosConfigProperties();}BeanCondition…