当前位置: 首页 > news >正文

设计模式之中介者

一、中介者设计模式概念

中介者模式(Mediator) 是一种行为设计模式, 能让你减少对象之间混乱无序的依赖关系。 该模式会限制对象之间的直接交互, 迫使它们通过一个中介者对象进行合作。

 适用场景

  • 当一些对象和其他对象紧密耦合以致难以对其进行修改时, 可使用中介者模式。
  • 当组件因过于依赖其他组件而无法在不同应用中复用时, 可使用中介者模式。
  • 如果为了能在不同情景下复用一些基本行为, 导致你需要被迫创建大量组件子类时, 可使用中介者模式

中介者设计模式的结构

  1. 组件 (Component) 是各种包含业务逻辑的类。 每个组件都有一个指向中介者的引用, 该引用被声明为中介者接口类型。 组件不知道中介者实际所属的类, 因此你可通过将其连接到不同的中介者以使其能在其他程序中复用。
  2. 中介者 (Mediator) 接口声明了与组件交流的方法, 但通常仅包括一个通知方法。 组件可将任意上下文 (包括自己的对象) 作为该方法的参数, 只有这样接收组件和发送者类之间才不会耦合。
  3. 具体中介者 (Concrete Mediator) 封装了多种组件间的关系。 具体中介者通常会保存所有组件的引用并对其进行管理, 甚至有时会对其生命周期进行管理。
  4. 组件并不知道其他组件的情况。 如果组件内发生了重要事件, 它只能通知中介者。 中介者收到通知后能轻易地确定发送者, 这或许已足以判断接下来需要触发的组件了。
    • 对于组件来说, 中介者看上去完全就是一个黑箱。 发送者不知道最终会由谁来处理自己的请求, 接收者也不知道最初是谁发出了请求。

代码如下:

          问题:实现一个机场的起飞管理系统,如果由驾驶员自己管理,会导致混乱,因此需要一个中介者来管理。
          解决方案:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使耦合松散,而且可以独立地改变他们之间的交互。
    中介者模式可帮助你减少各种UI组件之间的互相依赖关系。

#include <iostream>
#include <string>
class Staff;
class ControllerTower
{
public:virtual void notify(Staff* staff, std::string event)const = 0;
};
class Staff
{
protected:ControllerTower* m_controltower;std::string m_name;
public:Staff( std::string name, ControllerTower* controltower = nullptr) :m_name(name), m_controltower(controltower) {}std::string name() const {return m_name;}void setMediator(ControllerTower* controltower) {m_controltower = controltower;}
};class Pilot : public Staff
{
public:Pilot(std::string name) : Staff(name) {}void takeoff() {std::cout << name() << " 请求起飞." << std::endl;m_controltower->notify(this, "请求起飞");}void copy() {std::cout << name() << " is copying." << std::endl;}
};class GroundGrew : public Staff
{
public:GroundGrew(std::string name) : Staff(name) {}void maintainance() {std::cout << name() << " 请求维护." << std::endl;m_controltower->notify(this, "请求维护");}void copy() {std::cout << name() << " is copying." << std::endl;}
};class ControllerTower1 : public ControllerTower
{
private:Pilot* m_pilot1;Pilot* m_pilot2;Pilot* m_pilot3;GroundGrew* m_groundgrew1;
public:ControllerTower1(Pilot* pilot1, Pilot* pilot2, Pilot* pilot3, GroundGrew* groundgrew1): m_pilot1(pilot1), m_pilot2(pilot2), m_pilot3(pilot3), m_groundgrew1(groundgrew1) {m_pilot1->setMediator(this);m_pilot2->setMediator(this);m_pilot3->setMediator(this);m_groundgrew1->setMediator(this);}void notify(Staff* staff, std::string event)const override {std::cout << "控制塔:飞行员" << staff->name() << event << std::endl;if (event == "请求起飞"){m_groundgrew1->copy();if (staff != m_pilot1)m_pilot1->copy();if (staff != m_pilot2)m_pilot2->copy();if (staff != m_pilot3)m_pilot3->copy();}if (event == "请求维护"){m_pilot1->copy();m_pilot2->copy();m_pilot3->copy();}}
};
int main()
{Pilot* p1 = new Pilot("p1");Pilot* p2 = new Pilot("p2");Pilot* p3 = new Pilot("p3");GroundGrew* g1 = new GroundGrew("g1");ControllerTower1* controltower = new ControllerTower1(p1, p2, p3, g1);p1->takeoff();g1->maintainance();delete p1;delete p2;delete p3;delete g1;return 0;
}

 二、与其他模式的关系

  • 责任链模式 (opens new window)、 命令模式 (opens new window)、 中介者模式 (opens new window)和观察者模式 (opens new window)用于处理请求发送者和接收者之间的不同连接方式:
    • 责任链按照顺序将请求动态传递给一系列的潜在接收者, 直至其中一名接收者对请求进行处理。
    • 命令在发送者和请求者之间建立单向连接。
    • 中介者清除了发送者和请求者之间的直接连接, 强制它们通过一个中介对象进行间接沟通。
    • 观察者允许接收者动态地订阅或取消接收请求。
  • 外观模式 (opens new window)和中介者 (opens new window)的职责类似: 它们都尝试在大量紧密耦合的类中组织起合作。
    • 外观为子系统中的所有对象定义了一个简单接口, 但是它不提供任何新功能。 子系统本身不会意识到外观的存在。 子系统中的对象可以直接进行交流。
    • 中介者将系统中组件的沟通行为中心化。 各组件只知道中介者对象, 无法直接相互交流。
  • 中介者 (opens new window)和观察者 (opens new window)之间的区别往往很难记住。 在大部分情况下, 你可以使用其中一种模式, 而有时可以同时使用。 让我们来看看如何做到这一点。
    • 中介者的主要目标是消除一系列系统组件之间的相互依赖。 这些组件将依赖于同一个中介者对象。 观察者的目标是在对象之间建立动态的单向连接, 使得部分对象可作为其他对象的附属发挥作用。
    • 有一种流行的中介者模式实现方式依赖于观察者。 中介者对象担当发布者的角色, 其他组件则作为订阅者, 可以订阅中介者的事件或取消订阅。 当中介者以这种方式实现时, 它可能看上去与观察者非常相似。
    • 当你感到疑惑时, 记住可以采用其他方式来实现中介者。 例如, 你可永久性地将所有组件链接到同一个中介者对象。 这种实现方式和观察者并不相同, 但这仍是一种中介者模式。
    • 假设有一个程序, 其所有的组件都变成了发布者, 它们之间可以相互建立动态连接。 这样程序中就没有中心化的中介者对象, 而只有一些分布式的观察者。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • pyqt QGraphicsView 以鼠标为中心进行缩放
  • LTE协议栈学习
  • [创业之路-151] :职能部门/非经营部门 VS 业务部门/经营部门划分与职责
  • 为什么推荐使用英文版LabVIEW
  • 论文阅读:Omni-Kernel Network for Image Restoration
  • ESP32运行轻量级 Web 服务器入门(基于ESP-IDF)
  • 【天怡AI-注册安全分析报告-无验证方式导致安全隐患】
  • 从一个文本文件中挑选出符合条件的内容行
  • 大数据:快速入门Scala+Flink
  • 【word密码】word怎么限制格式,但可以修改文字?
  • 编写webpack插件自动上传sourceMap
  • Linux 基本指令(二)
  • 《linux系统》基础操作
  • 电力电网电线变电站输电线绝缘子无人机类数据集/农业植物病虫害类数据集/光伏板/工程煤矿矿场类数据集/道路类数据集
  • Android使用Flow封装一个FlowBus工具类
  • 《网管员必读——网络组建》(第2版)电子课件下载
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • git 常用命令
  • Gradle 5.0 正式版发布
  • spring-boot List转Page
  • STAR法则
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • web标准化(下)
  • 创建一个Struts2项目maven 方式
  • 关于Flux,Vuex,Redux的思考
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • ‌‌雅诗兰黛、‌‌兰蔻等美妆大品牌的营销策略是什么?
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • $(function(){})与(function($){....})(jQuery)的区别
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • $NOIp2018$劝退记
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (一) 初入MySQL 【认识和部署】
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .bat批处理(一):@echo off
  • .net 7 上传文件踩坑
  • .NET Core 中插件式开发实现
  • .Net mvc总结
  • .NET是什么
  • .NET之C#编程:懒汉模式的终结,单例模式的正确打开方式
  • //解决validator验证插件多个name相同只验证第一的问题
  • :如何用SQL脚本保存存储过程返回的结果集
  • @component注解的分类
  • @vue/cli 3.x+引入jQuery
  • [ C++ ] STL_vector -- 迭代器失效问题
  • [20161214]如何确定dbid.txt
  • [20190401]关于semtimedop函数调用.txt
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [Apio2012]dispatching 左偏树
  • [C++基础]-初识模板
  • [CSS]CSS 的背景