【C++】中介者模式

中介者模式(Mediator Pattern)是一种【行为型】设计模式,它通过一个中介对象来封装一系列对象之间的交互,使各对象不需要显式地相互引用,从而降低耦合度,并可以独立地改变它们之间的交互。这种模式将多对多的交互转化为一对多的交互,使系统更易于维护和扩展。

一、模式核心概念与结构

中介者模式包含四个核心角色:

  1. 抽象中介者(Mediator):定义统一的接口,用于各同事对象之间的通信。
  2. 具体中介者(Concrete Mediator):实现中介者接口,协调各同事对象的交互逻辑。
  3. 抽象同事类(Colleague):定义各同事类的公共接口,每个同事类都知道其中介者对象。
  4. 具体同事类(Concrete Colleague):实现抽象同事类,通过中介者与其他同事通信。

二、C++ 实现示例:聊天室系统

以下是一个简单的聊天室系统示例,演示如何使用中介者模式实现用户之间的通信:

#include <iostream>
#include <string>
#include <memory>
#include <unordered_map>
#include <vector>

// 前向声明
class ChatMediator;

// 抽象同事类:用户
class User {
protected:
    std::shared_ptr<ChatMediator> mediator;
    std::string name;

public:
    User(std::shared_ptr<ChatMediator> m, const std::string& n)
        : mediator(m), name(n) {}
    
    virtual ~User() = default;
    virtual void send(const std::string& message) = 0;
    virtual void receive(const std::string& message, const std::string& sender) = 0;
    
    std::string getName() const { return name; }
};

// 抽象中介者:聊天室
class ChatMediator {
public:
    virtual ~ChatMediator() = default;
    virtual void addUser(std::shared_ptr<User> user) = 0;
    virtual void removeUser(std::shared_ptr<User> user) = 0;
    virtual void sendMessage(const std::string& message, const std::string& sender, const std::string& receiver = "") = 0;
};

// 具体同事类:普通用户
class ConcreteUser : public User {
public:
    ConcreteUser(std::shared_ptr<ChatMediator> m, const std::string& n)
        : User(m, n) {}
    
    void send(const std::string& message) override {
        std::cout << name << " sends message: " << message << std::endl;
        mediator->sendMessage(message, name);
    }
    
    void sendPrivate(const std::string& message, const std::string& receiver) {
        std::cout << name << " sends private message to " << receiver << ": " << message << std::endl;
        mediator->sendMessage(message, name, receiver);
    }
    
    void receive(const std::string& message, const std::string& sender) override {
        std::cout << name << " received from " << sender << ": " << message << std::endl;
    }
};

// 具体中介者:具体聊天室
class ConcreteChatMediator : public ChatMediator {
private:
    std::unordered_map<std::string, std::shared_ptr<User>> users;

public:
    void addUser(std::shared_ptr<User> user) override {
        users[user->getName()] = user;
        std::cout << user->getName() << " joined the chat room" << std::endl;
    }
    
    void removeUser(std::shared_ptr<User> user) override {
        users.erase(user->getName());
        std::cout << user->getName() << " left the chat room" << std::endl;
    }
    
    void sendMessage(const std::string& message, const std::string& sender, const std::string& receiver) override {
        if (!receiver.empty()) {
            // 私聊
            auto it = users.find(receiver);
            if (it != users.end()) {
                it->second->receive(message, sender);
            } else {
                std::cout << "Error: User " << receiver << " not found" << std::endl;
            }
        } else {
            // 群聊
            for (auto& pair : users) {
                if (pair.first != sender) {  // 不发送给自己
                    pair.second->receive(message, sender);
                }
            }
        }
    }
};

// 客户端代码
int main() {
    // 创建聊天室(中介者)
    auto chatRoom = std::make_shared<ConcreteChatMediator>();
    
    // 创建用户(同事)
    auto alice = std::make_shared<ConcreteUser>(chatRoom, "Alice");
    auto bob = std::make_shared<ConcreteUser>(chatRoom, "Bob");
    auto charlie = std::make_shared<ConcreteUser>(chatRoom, "Charlie");
    
    // 将用户添加到聊天室
    chatRoom->addUser(alice);
    chatRoom->addUser(bob);
    chatRoom->addUser(charlie);
    
    // 发送群消息
    alice->send("Hello, everyone!");
    
    std::cout << "\n";
    
    // 发送私聊消息
    bob->sendPrivate("Hi Alice, how are you?", "Alice");
    
    return 0;
}

三、中介者模式的关键特性

  1. 集中控制交互
    • 中介者封装了对象之间的交互逻辑,使各对象不需要显式引用其他对象。
  2. 降低耦合度
    • 同事对象之间的依赖关系转移到中介者,减少了对象之间的直接依赖。
  3. 简化对象协议
    • 将多对多的交互转化为一对多的交互,使协议更清晰简单。
  4. 提高可维护性
    • 交互逻辑集中在中介者中,便于修改和维护。

四、应用场景

  1. 对象间通信复杂
    • 当对象之间的交互关系错综复杂,形成网状结构时。
    • 例如,GUI 组件之间的交互、多人游戏中的玩家通信。
  2. 减少子类化
    • 通过中介者封装交互逻辑,可以避免创建大量的子类。
  3. 复用对象
    • 当对象需要在不同环境中复用时,通过中介者可以解耦其与其他对象的关系。
  4. 分布式系统
    • 在分布式系统中,中介者可以作为消息代理或服务注册中心。

五、中介者模式与其他设计模式的关系

  1. 观察者模式
    • 中介者模式可以使用观察者模式实现中介者与同事之间的通信。
    • 同事对象可以注册到中介者,当中介者状态变化时通知同事。
  2. 单例模式
    • 中介者通常是系统中的核心组件,可以使用单例模式确保其唯一性。
  3. 工厂模式
    • 可以使用工厂模式创建中介者和同事对象,简化对象创建过程。

六、C++ 标准库中的中介者模式应用

  1. 消息队列
    • 如 Boost.Asio 中的异步消息处理,使用事件循环作为中介者协调各组件。
  2. 信号与槽机制
    • Qt 框架中的信号与槽机制,信号发送者和接收者通过信号系统(中介者)通信。
  3. STL 容器与算法
    • STL 容器和算法之间的交互可以看作是一种中介者模式的简化实现。

七、优缺点分析

优点:

  • 降低耦合:减少对象之间的直接依赖,提高系统可维护性。
  • 集中控制:将交互逻辑集中在中介者中,便于管理和修改。
  • 简化协议:使对象之间的协议更简单,易于理解和实现。
  • 支持复用:对象可以更容易地在不同环境中复用。

缺点:

  • 中介者过载:如果交互逻辑过于复杂,中介者可能变得庞大而难以维护。
  • 单点故障:中介者成为系统的核心,一旦出现问题可能影响整个系统。
  • 性能问题:中介者可能成为系统的瓶颈,特别是在高并发场景下。

八、实战案例:机场塔台调度系统

以下是一个机场塔台调度系统的实现示例,演示如何使用中介者模式管理飞机起降:

#include <iostream>
#include <string>
#include <memory>
#include <vector>

// 前向声明
class AirportTower;

// 抽象同事类:飞机
class Aircraft {
protected:
    std::shared_ptr<AirportTower> tower;
    std::string flightNumber;

public:
    Aircraft(std::shared_ptr<AirportTower> t, const std::string& flight)
        : tower(t), flightNumber(flight) {}
    
    virtual ~Aircraft() = default;
    virtual void requestLanding() = 0;
    virtual void requestTakeoff() = 0;
    virtual void receiveClearance(const std::string& message) = 0;
    
    std::string getFlightNumber() const { return flightNumber; }
};

// 抽象中介者:机场塔台
class AirportTower {
public:
    virtual ~AirportTower() = default;
    virtual void registerAircraft(std::shared_ptr<Aircraft> aircraft) = 0;
    virtual void handleLandingRequest(std::shared_ptr<Aircraft> aircraft) = 0;
    virtual void handleTakeoffRequest(std::shared_ptr<Aircraft> aircraft) = 0;
    virtual void sendClearance(const std::string& message, std::shared_ptr<Aircraft> aircraft) = 0;
};

// 具体同事类:客机
class PassengerAircraft : public Aircraft {
public:
    PassengerAircraft(std::shared_ptr<AirportTower> t, const std::string& flight)
        : Aircraft(t, flight) {}
    
    void requestLanding() override {
        std::cout << flightNumber << " requests landing" << std::endl;
        tower->handleLandingRequest(shared_from_this());
    }
    
    void requestTakeoff() override {
        std::cout << flightNumber << " requests takeoff" << std::endl;
        tower->handleTakeoffRequest(shared_from_this());
    }
    
    void receiveClearance(const std::string& message) override {
        std::cout << flightNumber << " received clearance: " << message << std::endl;
    }
};

// 具体中介者:国际机场塔台
class InternationalAirportTower : public AirportTower {
private:
    std::vector<std::shared_ptr<Aircraft>> aircrafts;
    bool runwayAvailable;

public:
    InternationalAirportTower() : runwayAvailable(true) {}
    
    void registerAircraft(std::shared_ptr<Aircraft> aircraft) override {
        aircrafts.push_back(aircraft);
        std::cout << aircraft->getFlightNumber() << " registered with tower" << std::endl;
    }
    
    void handleLandingRequest(std::shared_ptr<Aircraft> aircraft) override {
        if (runwayAvailable) {
            runwayAvailable = false;
            sendClearance("Runway clear for landing", aircraft);
        } else {
            sendClearance("Wait for landing clearance", aircraft);
        }
    }
    
    void handleTakeoffRequest(std::shared_ptr<Aircraft> aircraft) override {
        if (runwayAvailable) {
            runwayAvailable = false;
            sendClearance("Runway clear for takeoff", aircraft);
        } else {
            sendClearance("Wait for takeoff clearance", aircraft);
        }
    }
    
    void sendClearance(const std::string& message, std::shared_ptr<Aircraft> aircraft) override {
        aircraft->receiveClearance(message);
        
        // 模拟操作完成,释放跑道
        if (message.find("clear") != std::string::npos) {
            runwayAvailable = true;
            std::cout << "Runway is now available" << std::endl;
        }
    }
};

// 客户端代码
int main() {
    // 创建机场塔台(中介者)
    auto tower = std::make_shared<InternationalAirportTower>();
    
    // 创建飞机(同事)
    auto flight1 = std::make_shared<PassengerAircraft>(tower, "CA1234");
    auto flight2 = std::make_shared<PassengerAircraft>(tower, "MU5678");
    
    // 注册飞机到塔台
    tower->registerAircraft(flight1);
    tower->registerAircraft(flight2);
    
    // 飞机请求操作
    flight1->requestLanding();
    flight2->requestTakeoff();
    
    return 0;
}

九、实现注意事项

  1. 避免中介者过度复杂
    • 中介者应专注于协调对象间的交互,避免承担过多业务逻辑。
  2. 松耦合设计
    • 中介者和同事对象之间应保持松耦合,通过抽象接口通信。
  3. 中介者生命周期管理
    • 确保中介者的生命周期覆盖所有同事对象的生命周期。
  4. 线程安全
    • 在多线程环境中,中介者的操作可能需要同步机制(如互斥锁)。

中介者模式是 C++ 中处理对象间复杂交互的重要工具,通过引入中介者对象,可以将网状的对象关系转化为星型结构,降低系统耦合度,提高可维护性和可扩展性。


如果这篇文章对你有所帮助,渴望获得你的一个点赞!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OpenC++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值