基于C++的《Head First设计模式》笔记——中介者模式

目录

一.专栏介绍

二.中介者模式概念

三.案例与代码

四.中介者模式的优点

五.中介者模式的缺点

六.中介者模式的用途

七.总结


一.专栏介绍

本专栏是我学习《head first》设计模式的笔记。这本书中是用Java语言为基础的,我将用C++语言重写一遍,并且详细讲述其中的设计模式,涉及是什么,为什么,怎么做,自己的心得等等。希望阅读者在读完我的这个专题后,也能在开发中灵活且正确的使用,或者在面对面试官时,能够自信地说自己熟悉常用设计模式。

本章将开始**中介者模式(Mediator Pattern)**的学习。

二.中介者模式概念

使用中介者模式来集中相关对象之间复杂的沟通和控制方式。

用一个中介者对象封装一系列对象之间的交互逻辑,让原本相互依赖、直接通信的对象解耦,所有对象只和中介者通信,不再直接引用彼此

当多个对象之间存在复杂的网状依赖关系 时(比如 A 调用 B、B 调用 C、C 调用 A),代码会变得难以维护、修改和扩展。中介者模式把网状结构 变成星型结构所有对象只对接中介者,中介者统一调度交互。中介者就是那颗星星

网状图:

星状图:

核心角色:

  1. 抽象中介者(Mediator):定义统一的交互接口,声明对象之间通信的方法;

  2. 具体中介者(ConcreteMediator):实现抽象中介者,持有所有交互对象的引用,处理具体的交互逻辑;

  3. 抽象同事类(Colleague):定义公共方法,持有中介者的引用;

  4. 具体同事类(ConcreteColleague):实现自身业务逻辑,需要交互时,通过中介者通知其他对象。

三.案例与代码

我们实现一个多人聊天室的demo,当聊天室里的用户发送消息时,其他人都会收到。这里的用户就是中介者模式的同事类对象,他们通过中介者类将消息发送给其他人。

代码如下:

mediatorPattern.h:

cpp 复制代码
#pragma once
#include <string>
#include <vector>
#include <iostream>
using namespace std;

class User;

// 中介者抽象类
class Mediator
{
public:
	virtual ~Mediator() = default;
	// 依靠User引用将消息发送给User
	virtual void send(const string& message, User* sender) = 0;
	// 添加User引用
	virtual void addUser(User* nUser) = 0;
};

class User
{
public:
	User(Mediator* m, string n):
		mediator(m), name(n)
	{}
	virtual ~User() = default;
	// 向其他人发送消息,用中介者引用来发送
	virtual void send(const string& message) = 0;
	// 提供给中介者使用,中介者用这个函数将消息发送给自己
	virtual void receive(const string& message) = 0;
protected:
	Mediator* mediator;			// 中介者引用
	string name;				// 用户姓名
};

// 中介者具体类
class ConcreteMediator : public Mediator
{
public:
	void send(const string& message, User* sender) override
	{
		for (const auto& user : users)
		{
			// 不发送给自己(不回显)
			if (user != sender) user->receive(message);
		}
	}
	void addUser(User* nUser)
	{
		users.push_back(nUser);
	}
private:
	vector<User*> users;				// 子类自定义数据结构和提供添加等方法,更灵活
};

class ConcreteUser : public User
{
public:
	ConcreteUser(Mediator* m, string n):
		User(m, n)
	{}
	virtual ~ConcreteUser() = default;
	void send(const string& message) override
	{
		mediator->send(message, this);
	}
	void receive(const string& message)
	{
		cout << name << "收到消息:" << message << endl;
	}
};

代码说明:

  • 这里的用户类是中介者模式概念里的同事类。
  • 用户类和中介者类持有彼此的引用。
  • 中介者类管理用户的数据结构(比如这里的vector)交由具体中介者类定义并实现addUser()虚函数,这样更灵活。
  • 用户类send()方法调用中介者引用的send()方法,仅与中介者"这颗星星"交互,中介者再调用各个用户类的引用的receive()方法让他们接收。

main.cpp:

cpp 复制代码
#include "mediatorPattern.h"

int main()
{
	Mediator* mediator = new ConcreteMediator();

	User* Bob = new ConcreteUser(mediator, "Bob");
	User* Mike = new ConcreteUser(mediator, "Mike");
	User* John = new ConcreteUser(mediator, "John");

	mediator->addUser(Bob);
	mediator->addUser(Mike);
	mediator->addUser(John);

	Bob->send("Hello everyone!");
	cout << endl;
	Mike->send("How do you guys think?");
	cout << endl;
	John->send("Good morning!");

	delete mediator;
	delete Bob;
	delete Mike;
	delete John;

	return 0;
}

运行输出:

每个用户发送的消息都被其他用户收到了!

四.中介者模式的优点

  • 通过将中介者支持的对象从系统解耦,增加了对象的复用性。附和单一职责原则。

  • 通过将控制逻辑集中,简化了系统的维护。集中管理交互规则,修改逻辑只需修改中介者 。附和开闭原则

五.中介者模式的缺点

  • 中介者模式的一个缺点是,如果设计不当,中介者对象本身会变得过度复杂。

六.中介者模式的用途

  • 多个对象之间存在复杂的相互调用(如GUI组件、聊天室、调度系统)。
  • 想要简化对象之间的依赖关系,提高代码可维护性。
  • 需要集中控制一组对象的交互行为。

七.中介者模式 vs 观察者模式

观察者模式 == 老师上课

老师(主题)一说话,所有学生(观察者)都听到。一对多、自动广播、不需要中间转发。

中介者模式 == 聊天室

所有人(用户)不直接对话,都发给聊天室(中介者),中介者转发。多对多、互相不认识、完全靠中介调度。

八.总结

  • 中介者模式核心:解耦网状依赖,转为星型交互,统一调度

  • 核心角色:抽象中介者、具体中介者、抽象同事、具体同事;

  • 核心逻辑:对象不直接通信,全部通过中介者转发 / 调度。

相关推荐
夜瞬1 分钟前
NLP学习笔记02:文本表示方法——从词袋模型到 BERT
笔记·学习·自然语言处理
xuhaoyu_cpp_java6 分钟前
MySql学习(二)
经验分享·笔记·学习·mysql
老王以为40 分钟前
深入理解 AbortController:从底层原理到跨语言设计哲学
javascript·设计模式·node.js
浅念-1 小时前
从LeetCode入门位运算:常见技巧与实战题目全解析
数据结构·数据库·c++·笔记·算法·leetcode·牛客
talen_hx2961 小时前
《零基础入门Spark》学习笔记 Day 16
笔记·学习·spark
kobesdu1 小时前
【ROS2实战笔记-3】RViz2图形底层与调试暗坑
笔记·机器人·ros·rviz
深蓝海拓2 小时前
基于QtPy (PySide6) 的PLC-HMI工程项目(八)在上位机中解析上行报文
网络·笔记·python·学习·plc
likerhood2 小时前
抽象工厂设计模式(Abstract Factory Pattern)
设计模式
张涛酱1074562 小时前
AskUserQuestionTool 深入解析:构建人机协作的交互桥梁
spring·设计模式·ai编程
Duang2 小时前
AI 真能自己写出整个 Windows 系统吗?我做了一场无监督实验
算法·设计模式·架构