中介者模式

一、简介
1. 定义
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
2. 应用场景
适用于系统中大量的对象需要相互的依赖,并且彼此间的依赖关系复杂混乱,此时在重构过程中,可以用一个中间类来管理这些对象之间的依赖关系。
3.优缺点
优点:
将多个互相依赖的类进行解耦,使得这些有交互的对象松耦合;
增加交互对象时,只需要在中介类中进行修改即可,不需要变动其他的对象实现;
缺点:
中介类可能会变得复杂,甚至会发展到功能庞大,违反类的单一职责。
4. 类图


二、 代码示例
1. 场景简介
在组队枪战游戏中,突击小队需要通过通讯设备来完成战术的安排与实施,队长主要负责下达命令,队员根据战况请求支援。

#ifndef MEDIATOR_H
#define MEDIATOR_H

#include <QString>
#include <QDebug>
#include <QMap>

class IMediator;

class IUser
{
public:
    IUser(QString name)
        : m_name(name)
    {};
    virtual ~IUser() {};

    inline QString name() { return m_name; };
    virtual void send(QString msg, IMediator *mediator) = 0;
    virtual void notify(QString msg) = 0;

private:
    QString            m_name;
};

class IMediator
{
public:
    IMediator() {};
    virtual ~IMediator() {};

    virtual void registeUser(IUser *user)
    {
        QString name = user->name();
        if (!m_userMap.contains(name))
        {
            m_userMap.insert(name, user);
        }
    };
    virtual void unregisterUser(IUser *user)
    {
        m_userMap.remove(user->name());
    };
    virtual void sendMsg(QString msg, IUser *sender) = 0;

protected:
    QMap<QString, IUser*>        m_userMap;
};

class GameMediator : public IMediator
{
public:
    GameMediator() {};
    virtual ~GameMediator() {};

    virtual void sendMsg(QString msg, IUser *sender)
    {
        foreach (IUser* user, m_userMap)
        {
            if (user->name() != sender->name())
            {
                user->notify(msg);
            }
        }
    };
};

class UserImp : public IUser
{
public:
    UserImp(QString name)
        : IUser(name)
    {};
    virtual ~UserImp() {};

    virtual void send(QString msg, IMediator *mediator)
    {
        if (nullptr != mediator)
        {
            mediator->sendMsg(msg, this);
        }
    };
    virtual void notify(QString msg)
    {
        qDebug() << name() << "receive msg: " << msg;
    };
};

#if 1

#define FREE_OBJ(obj)        if (nullptr != (obj)){delete (obj); (obj) = nullptr;}

void main()
{
    IMediator *mediator = new GameMediator;

    UserImp *captain = new UserImp("Game Captain");
    UserImp *playerA = new UserImp("XiaoMing");
    UserImp *playerB = new UserImp("XiaoQiang");

    mediator->registeUser(captain);
    mediator->registeUser(playerA);
    mediator->registeUser(playerB);

    captain->send("Ready?", mediator);

    playerA->send("Help!", mediator);

    FREE_OBJ(mediator);
    FREE_OBJ(captain);
    FREE_OBJ(playerA);
    FREE_OBJ(playerB);

    getchar();
}

#endif // 1

#endif // !MEDIATOR_H