实战设计模式之中介者模式

概述

        中介者模式是一种强大且灵活的设计模式,适用于需要优化对象间通信的场景。中介者模式通过引入一个中介对象,来封装一系列对象之间的交互。在没有中介者的情况下,这些对象之间可能会直接相互引用,导致系统中的类紧密耦合,难以维护和扩展。而通过使用中介者模式,可以将对象间的通信集中到一个中介者对象中,从而减少了对象之间的直接依赖,提高了系统的灵活性和可维护性。

        空中交通管制是现实生活中运用中介者模式的一个典型例子。在航空业中,空中交通管制系统扮演着中介者的角色。每架飞机就像是同事类,它们需要与其他飞机进行通信,以确保飞行的安全和效率。然而,如果让每架飞机都直接与其它所有飞机进行通信,不仅复杂度极高,而且容易引发混乱甚至危险。因此,空中交通管制员作为中介者,负责协调所有飞机的起飞、降落以及飞行路径,确保它们之间不会发生碰撞。在这个过程中,飞机只需遵循空中交通管制员的指示,而不需要知道其他飞机的具体情况。

基本原理

        中介者模式的核心思想是:通过引入一个中介对象,来封装一系列对象之间的交互,从而减少这些对象之间的直接依赖。在没有中介者的情况下,对象之间可能会形成复杂的网状结构,导致系统难以维护和扩展。中介者模式使得每个对象只需与中介者进行通信,而不需要知道其他对象的存在或操作方式,这大大降低了系统的耦合度,并提高了灵活性和可维护性。

        中介者模式主要由以下三个核心组件构成。

        1、抽象中介者。定义了同事类与中介者之间通信的接口,通常是一个接口或抽象类,具体实现留给子类完成。目的是为具体的中介者提供一个统一的接口,以便于同事类与中介者之间的交互。

        2、具体中介者。实现了抽象中介者的接口,包含了对同事类的引用,并负责处理同事类之间的交互逻辑。具体中介者了解所有同事类,并能够根据需要调用同事类的方法,或者通知其他同事类发生了某些事件。

        3、同事类。每个同事类都知道自己应该与中介者进行通信,但不知道也不关心其他同事类的存在或操作。同事类通常会持有对中介者的引用,并通过中介者发送消息给其他同事类。同事类只负责自身的业务逻辑,而不直接与其他同事类交互,所有的交互都通过中介者来进行。

        基于上面的核心组件,中介者模式的实现主要有以下四个步骤。

        1、定义抽象中介者。创建一个接口或抽象类,定义同事类与中介者之间通信的方法。这些方法通常是用于发送消息,或通知其他同事类发生的变化。

        2、创建具体中介者。实现抽象中介者接口,创建具体的中介者类。在具体中介者中,管理所有同事类的引用,并实现同事类之间交互的具体逻辑。确保具体中介者能够接收来自一个同事类的消息,并将消息转发给相关的同事类。

        3、定义同事类。创建同事类,它持有一个指向中介者的引用。同事类通过中介者发送消息给其他同事类,而不是直接与它们通信。同事类还应包含一些基本的行为和状态,以及处理接收到的消息的方法。

        4、集成同事类与中介者。将同事类注册到中介者中,使得中介者可以管理这些同事类。当同事类需要与其他同事类通信时,它通过中介者发送消息,而不是直接调用其他同事类的方法。

实战代码

        在下面的实战代码中,我们使用中介者模式模拟了空中交通管制的实现。

        首先,我们定义了抽象中介者接口CAirTrafficControl。它声明了注册飞机和更新位置的方法,为具体中介者提供了统一的操作接口。

        接着,通过CConcreteAirTrafficControl实现了这些方法,并添加了检查潜在碰撞的功能。在该类中,使用一个哈希表m_mapAircraft来存储所有已注册飞机的引用,另一个哈希表m_mapPosition记录每架飞机的位置坐标。每当有飞机更新其位置时,就会调用UpdatePosition方法。该方法不仅更新了飞机的位置信息,还会触发CheckForCollisions函数,以检查是否有任何两架飞机的距离小于预设的安全距离SAFE_DISTANCE。如果检测到可能的碰撞,AvoidCollision方法将被调用,通知相关飞机采取避让措施。

        然后,我们定义了同事类CAircraft。它代表系统中的各个飞机,并持有一个指向中介者的引用,可以通过中介者报告自己的当前位置。每个飞机实例都知道如何向空中交通控制中心报告其最新位置,并且当接收到碰撞警告时,会打印出相应的避让信息。

        最后,在main函数中,我们创建了一个具体的空中交通控制中心实例,并注册了两架飞机。通过调用UpdatePosition方法更新这两架飞机的位置,模拟它们的移动过程。随着飞机2逐渐靠近飞机1,最终触发了碰撞检测机制,导致两架飞机都收到了避让指令,以避免潜在的碰撞。

#include <iostream>
#include <unordered_map>
#include <string>
#include <cmath>

using namespace std;

class CAircraft;

// 抽象中介者
class CAirTrafficControl
{
public:
    virtual void RegisterAircraft(const string& id, CAircraft* aircraft) = 0;
    virtual void UpdatePosition(const string& senderId, double x, double y) = 0;
};

// 具体中介者:空中交通控制中心
class CConcreteAirTrafficControl : public CAirTrafficControl
{
public:
    void RegisterAircraft(const string& id, CAircraft* aircraft) override
    {
        m_mapAircraft[id] = aircraft;
    }

    void UpdatePosition(const string& senderId, double x, double y) override
    {
        m_mapPosition[senderId] = {x, y};
        CheckForCollisions(senderId);
    }

    void CheckForCollisions(const string &senderId);

private:
    bool IsTooClose(double x1, double y1, double x2, double y2)
    {
        return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)) < SAFE_DISTANCE;
    }

private:
    struct Position
    {
        double x;
        double y;
    };

    unordered_map<string, CAircraft*> m_mapAircraft;
    unordered_map<string, Position> m_mapPosition;
    // 安全距离
    const double SAFE_DISTANCE = 10.0;
};

// 同事类:飞机
class CAircraft
{
public:
    CAircraft(const string& id, CAirTrafficControl* atc) : m_id(id), m_pAtc(atc) {}

    string GetId() const { return m_id; }

    void UpdatePosition(double x, double y)
    {
        cout << m_id << " updates pos to (" << x << ", " << y << ")" << endl;
        m_pAtc->UpdatePosition(m_id, x, y);
    }

    void AvoidCollision(const string& otherId)
    {
        cout << GetId() << " taking action to avoid collision with " << otherId << endl;
    }

private:
    string m_id;
    CAirTrafficControl* m_pAtc;
};

void CConcreteAirTrafficControl::CheckForCollisions(const string& senderId)
{
    auto itSender = m_mapPosition.find(senderId);
    if (itSender == m_mapPosition.end())
    {
        return;
    }

    for (auto& it : m_mapPosition)
    {
        if (it.first != senderId && 
            IsTooClose(itSender->second.x, itSender->second.y, it.second.x, it.second.y))
        {
            cout << "Potential collision between " << senderId << " and " << 
                it.first << endl;
            m_mapAircraft[it.first]->AvoidCollision(senderId);
            m_mapAircraft[senderId]->AvoidCollision(it.first);
        }
    }
}

int main()
{
    CConcreteAirTrafficControl atc;

    CAircraft aircraft1("Flight 101", &atc);
    CAircraft aircraft2("Flight 202", &atc);

    atc.RegisterAircraft(aircraft1.GetId(), &aircraft1);
    atc.RegisterAircraft(aircraft2.GetId(), &aircraft2);

    // 飞机1更新位置
    aircraft1.UpdatePosition(100, 100);
    // 飞机2更新位置,接近飞机1
    aircraft2.UpdatePosition(150, 150);
    // 飞机2进一步靠近飞机1,触发碰撞警告
    aircraft2.UpdatePosition(105, 105);
    return 0;
}

总结

        在复杂的系统中,组件间的通信往往变得异常复杂。中介者模式提供了一种集中管理这些通信的方式,使得组件间的交互逻辑更加简洁明了。由于同事类之间的交互被集中在中介者中,因此当需要添加新的同事类或修改现有的交互逻辑时,只需要调整中介者的实现即可,而不会影响到其他同事类。这大大提高了系统的灵活性和可维护性,有助于快速响应需求变化。

        但如果系统中有大量同事类频繁地与中介者进行交互,那么中介者可能会成为性能瓶颈。特别是在高并发环境下,中介者的处理能力直接影响到整个系统的吞吐量和响应速度。因此,在设计中介者时,需要特别注意其性能表现,避免出现单点故障。

评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

希望_睿智

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

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

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

打赏作者

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

抵扣说明:

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

余额充值