什么是中介者模式?
Mediator Pattern Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.
换言之,将各个类与其他类交互的逻辑单独出来放在封装在一个Mediator类里面,它负责各个类之间的交互,这样的好处是各个类(同事类)可以专注于自己的职责,即高内聚。同时降低与其他类的联系,即低耦合。
类图结构:
中介者模式常用于UI设计,类图如下:
当然,同事类不一定是继承自同一祖先。
Example:
例子描述的是Alarm、Calendar、CoffeePot三个类之间的交互通过Mediator来完成,关系图如下:
colleague.h如下:
#ifndef __COLLEAGUE_H__
#define __COLLEAGUE_H__
#include <map>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
class Mediator;
class Calender
{
public:
Calender(Mediator* pMediator);
void addEvent(int timeInSeconds, std::string desc);
bool checkEvent( int timeInSeconds );
private:
Mediator* m_pMediator;
map<int, string> m_mapCalender;
};
class Alarm
{
public:
Alarm(Mediator* pMediator);
void setTime(int nTime);
int getTime();
void setTimer(int timeInseconds);
void start();
void stop();
bool isThereAlarm( int tm );
private:
int m_nTime;
vector<int> times;
Mediator* m_pMediator;
};
class CoffeePot
{
public:
CoffeePot(Mediator* pMediator, int nStart = 100000);
void cook(int nStart);
void ready( int tm );
bool isReady( int tm );
private:
int m_nStart;
Mediator* m_pMediator;
};
#endif
colleague.cpp如下:
#include "mediator.h"
#include "colleague.h"
Calender::Calender( Mediator* pMediator )
{
m_pMediator = pMediator;
}
void Calender::addEvent( int timeInSeconds, string desc )
{
m_mapCalender[timeInSeconds] = desc;
cout << "An event is added to calender: " << desc << " at " << timeInSeconds << endl;
m_pMediator->addEventToCalender(timeInSeconds);
}
bool Calender::checkEvent( int timeInSeconds )
{
map<int, string>::const_iterator iter = m_mapCalender.find(timeInSeconds);
if (iter != m_mapCalender.end())
{
string desc = iter->second;
cout << desc << " is due!" << endl;
return true;
}
return false;
}
Alarm::Alarm( Mediator* pMediator )
{
m_pMediator = pMediator;
}
void Alarm::setTimer( int timeInseconds )
{
cout << "Alarm is set at " << timeInseconds << endl;
times.push_back(timeInseconds);
}
void Alarm::start()
{
cout << "Alarm starts at " << m_nTime << endl;
m_pMediator->startAlarm(m_nTime);
}
void Alarm::stop()
{
cout << "Alarm stops" << endl;
m_pMediator->stopAlarm();
}
bool Alarm::isThereAlarm( int tm )
{
vector<int>::const_iterator iter = times.begin();
for (; iter != times.end(); ++iter)
if (*iter == tm)
return true;
return false;
}
void Alarm::setTime( int nTime )
{
m_nTime = nTime;
}
int Alarm::getTime()
{
return m_nTime;
}
CoffeePot::CoffeePot( Mediator* pMediator, int nStart /*= 100000*/ )
{
m_pMediator = pMediator;
m_nStart = nStart;
}
void CoffeePot::cook(int nStart)
{
cout << "Start cooking coffee at " << nStart << endl;
m_nStart = nStart;
}
void CoffeePot::ready( int tm )
{
cout << "Coffee is ready at " << tm << endl;
m_pMediator->coffeeIsReady();
}
bool CoffeePot::isReady( int tm )
{
if (tm - m_nStart >= 20) //it takes 20 secs to make coffee
{
m_nStart = 100000;
return true;
}
return false;
}
mediator.h如下:
#ifndef __MEDIATOR_H__
#define __MEDIATOR_H__
class Alarm;
class Calender;
class CoffeePot;
class Mediator
{
public:
Mediator() {}
void setAlarm(Alarm* pAlarm);
void setCalender(Calender* pCalender);
void setCoffeePot(CoffeePot* pCoffeepot);
void startAlarm(int timeInSeconds);
void stopAlarm();
void addEventToCalender(int timeInSeconds);
void coffeeIsReady();
private:
Alarm* m_pAlarm;
Calender* m_pCalender;
CoffeePot* m_pCoffeePot;
};
#endif
mediator.cpp如下:
#include "colleague.h"
#include "mediator.h"
void Mediator::startAlarm( int timeInSeconds )
{
m_pCalender->checkEvent(timeInSeconds);
}
void Mediator::stopAlarm()
{
m_pCoffeePot->cook(m_pAlarm->getTime());
}
void Mediator::coffeeIsReady()
{
m_pAlarm->start();
}
void Mediator::addEventToCalender( int timeInSeconds )
{
m_pAlarm->setTimer(timeInSeconds);
}
void Mediator::setAlarm( Alarm* pAlarm )
{
m_pAlarm = pAlarm;
}
void Mediator::setCalender( Calender* pCalender )
{
m_pCalender = pCalender;
}
void Mediator::setCoffeePot( CoffeePot* pCoffeepot )
{
m_pCoffeePot = pCoffeepot;
}
测试代码main.cpp如下:
#include "colleague.h"
#include "mediator.h"
int main()
{
Mediator mediator;
Alarm alarm(&mediator);
Calender calender(&mediator);
CoffeePot coffeePot(&mediator);
mediator.setAlarm(&alarm);
mediator.setCalender(&calender);
mediator.setCoffeePot(&coffeePot);
calender.addEvent(30, "get up");
for (int tm = 0; tm < 1000; ++tm)
{
alarm.setTime(tm);
if (alarm.isThereAlarm(tm))
{
alarm.start();
alarm.stop();
}
if (coffeePot.isReady(tm))
coffeePot.ready(tm);
}
return 0;
}
最终运行结果如下: