【设计模式】中介者

时间:2021-12-22 21:59:12

中介者,说白了跟市面上黑中介类似。当然这个中介,开发者是可以控制其行为的。也是在一定的信任关系上建立的。

该模式要解决的问题是,一堆对象之间交叉耦合问题。

网上看过群聊的例子。如果没有任何一个平台,多人之间的会话会是什么样的呢?不举多人,就三个吧A想把一句话说给BC,那么他首先要知道B和C在哪儿,然后分别告诉对方,自己想说的事情。如果再加一个人呢?

问题很明显,此时各种群聊工具应运而生。我写了个简单的demo:

/***************************************************************************
 * 
 * Copyright (c) 2013 itegel.com, Inc. All Rights Reserved
 * 
 **************************************************************************/
 
/**
 * @file test_mediator.cpp
 * @author itegel
 * @date 2013/06/05 17:00:07
 * @brief 群聊的例子
 *  
 **/
#include <string>
#include <vector>
#include <iostream>
#include <time.h>
#include <sstream>
using namespace std;

class Mediator;
//抽象colleague
class Colleague{
    public:
        Colleague(string & name, Mediator * media):_name(name){
            _mediator = media;
        }
        void SetName(string & name){
            _name = name;
        }
        string GetName(){
            return _name;
        }
        
        void SetContent(string content){
            _content = content;
        }
        string GetContent(){
            return _content;
        }

        virtual void talk(){
            cout<<this->GetName()<<" saied:"<<this->GetContent()<<endl;
        }
        Mediator * GetMediator(){
            return _mediator;
        }

    protected:
        string _name;
        string _content;
        Mediator * _mediator;
};

class Mediator{
    public:
        Mediator(){
            _history = "";
        }
        void AddColleague(Colleague * clg){
            _colleagues.push_back(clg);
        }
        virtual void Notify(){
            for(vector<Colleague *>::iterator iter = _colleagues.begin(); iter != _colleagues.end(); iter++){
                (*iter)->talk();
            }
        }

        void AppendHistory(string new_content){
            time_t t = time(NULL);
            struct tm* ct = localtime(&t);
            ostringstream oss;
            oss<<ct->tm_mon + 1<<"-"<<ct->tm_mday<<" "<<ct->tm_hour<<":"<<ct->tm_min<<":"<<ct->tm_sec<<" ";
            oss<<new_content<<"\n";
            _history += oss.str();
        }

        string GetHistory(){
            return _history;
        }
    protected:
        vector<Colleague *> _colleagues;
        string _history;
};

class ColleagueA : public Colleague{
    public:
        ColleagueA(string name, Mediator * media):Colleague(name, media){
        }
        ~ColleagueA(){}
        
        virtual void talk(){
            cout<<this->GetName()<<" saied:"<<this->GetContent()<<endl;
            _mediator->AppendHistory(this->GetName()+":"+this->GetContent());
        }
};

class ColleagueB : public Colleague{
    public:
        ColleagueB(string name, Mediator * media):Colleague(name, media){
        }
        ~ColleagueB(){}
        virtual void talk(){
            cout<<this->GetName()<<" saied:"<<this->GetContent()<<endl;
            _mediator->AppendHistory(this->GetName()+":"+this->GetContent());
        }
};

class Hi : public Mediator{
    public:
        Hi(){}
        ~Hi(){}
};



int main(){
    Hi hi;
    ColleagueA * A1 = new ColleagueA("A1", &hi);    
    ColleagueB * B1 = new ColleagueB("B1", &hi);    
    ColleagueB * B2 = new ColleagueB("B2", &hi);    
    hi.AddColleague(A1);
    hi.AddColleague(B1);
    hi.AddColleague(B2);

    A1->SetContent("I am hungry!");
    B1->SetContent("I am hungry too!");
    B2->SetContent("Let's go out and have sth. to eat!");
    hi.Notify();

    sleep(1);

    A1->SetContent("田老师?");
    B1->SetContent("米线吧?");
    B2->SetContent("有会,还是食堂吧!");
    hi.Notify();

    sleep(1);
    cout<<endl<<A1->GetName()<<" 查看聊天记录:"<<endl;
    cout<<A1->GetMediator()->GetHistory()<<endl;;
    return 0;
}

执行结果:

【设计模式】中介者

A1 saied:I am hungry!
B1 saied:I am hungry too!
B2 saied:Let's go out and have sth. to eat!
A1 saied:田老师?
B1 saied:米线吧?
B2 saied:有会,还是食堂吧!

A1 查看聊天记录:
6-5 19:34:59 A1:I am hungry!
6-5 19:34:59 B1:I am hungry too!
6-5 19:34:59 B2:Let's go out and have sth. to eat!
6-5 19:35:0 A1:田老师?
6-5 19:35:0 B1:米线吧?
6-5 19:35:0 B2:有会,还是食堂吧!


引入mediator之后,其实 每个对象不用感知有多少个其他对象(当然也可以通过一些接口从中介者那里获取),只需要把自己该干的干好,需要跟别人协调的,告诉中介者就好,中介者负责把相应的任务分发出去。这样多个对象之间只与mediator耦合,将N*M的关系减少为了N*1的关系。

中介者实际实现可以有很多种,要看具体应用。

用中介者的坏处估计也是跟黑中介类似,比如租房,实际上我只需要跟房东打交道就好。但是因为中介的介入,我同样的接口(比如电话号码)可能还得暴露给中介者!