中介者模式:用一个中介对象封装一系列对象的交互,中介者使各个对象不需要显示的相互调用,从而使其松耦合,并且可以独立的改变他们之间的交互。
假设有这样一个场景,拍摄了一部电影,前期拍摄完成之后,后期需要给电影配上音乐和特效,在使用播放软件播放电影的时候,视频、音乐甚至是软件显示的时间轴需要同步进行。
当我们点击【暂停】的时候,画面停止不动,声音也不在播放;
当我们再次点击画面的时候,时间轴继续前进,画面播放,声音也播放出来了。
下面咱们就要把上面的这个场景使用软件实现出来,首先选定一个设计模式,也许你会觉得使用观察者模式是一个很好的办法,的确是一个好办法。但是会有一个问题,当操作播放滚动条的时候,操作界面是被观察的对象,声音、图像是观察者;当点击图像的时候,图像就又变成了被观察对象,播放界面和声音变成了观察者。
也就是说,观察者和被观察者对象是不同的在变化着,使用观察者模式处理起来就比较麻烦了,使用中介者就很方便了。
首先定义抽象的中介者:
class IMediator {
public:
IMediator();
~IMediator();
//播放
virtual void playExceptUI(std::string time);
virtual void playExceptMP4(std::string time);
virtual void playExceptMap(std::string time);
//加速
virtual void speedUpExceptUI(int r);
virtual void speedUpExceptMP4(int r);
virtual void speedUpExceptMap(int r);
//时间
virtual void playTimeExceptUI(std::string t);
virtual void playTimeExceptMP4(std::string t);
virtual void playTimeExceptMap(std::string t);
protected:
UICollagen* _uiCollagen;
MapCollagen* _mapCollagen;
MP4Collagen* _mp4Collagen;
};
IMediator::IMediator() {
}
IMediator::~IMediator() {
}
void IMediator::playExceptUI(std::string time) {
}
void IMediator::playExceptMP4(std::string time) {
}
void IMediator::playExceptMap(std::string time) {
}
void IMediator::speedUpExceptUI(int r) {
}
void IMediator::speedUpExceptMP4(int r) {
}
void IMediator::speedUpExceptMap(int r) {
}
void IMediator::playTimeExceptUI(std::string t) {
}
void IMediator::playTimeExceptMP4(std::string t) {
}
void IMediator::playTimeExceptMap(std::string t) {
}
定义具体的中介者:
class MyMediator :public IMediator {
public:
MyMediator();
//播放
virtual void playExceptUI(std::string time)override;
virtual void playExceptMP4(std::string time)override;
virtual void playExceptMap(std::string time)override;
//加速
virtual void speedUpExceptUI(int r)override;
virtual void speedUpExceptMP4(int r)override;
virtual void speedUpExceptMap(int r)override;
//时间
virtual void playTimeExceptUI(std::string t)override;
virtual void playTimeExceptMP4(std::string t)override;
virtual void playTimeExceptMap(std::string t)override;
};
MyMediator::MyMediator() {
_uiCollagen = new UICollagen(this);
_mapCollagen = new MapCollagen(this);
_mp4Collagen = new MP4Collagen(this);
}
void MyMediator::playExceptUI(std::string time) {
_mapCollagen->palyMap(time);
_mp4Collagen->palyMp4();
}
void MyMediator::playExceptMP4(std::string time) {
_mapCollagen->palyMap(time);
_uiCollagen->playUI(time);
}
void MyMediator::playExceptMap(std::string time) {
_mp4Collagen->palyMp4();
_uiCollagen->playUI(time);
}
void MyMediator::speedUpExceptUI(int r) {
_mapCollagen->speedUpMap(r);
_mp4Collagen->speedUpMp4(r);
}
void MyMediator::speedUpExceptMP4(int r) {
_uiCollagen->speedUpUI(r);
_mapCollagen->speedUpMap(r);
}
void MyMediator::speedUpExceptMap(int r) {
_uiCollagen->speedUpUI(r);
_mp4Collagen->speedUpMp4(r);
}
void MyMediator::playTimeExceptUI(std::string t) {
_mapCollagen->playTimeMap(t);
_mp4Collagen->playTimeMp4(t);
}
void MyMediator::playTimeExceptMP4(std::string t) {
_uiCollagen->playTimeUI(t);
_mapCollagen->playTimeMap(t);
}
void MyMediator::playTimeExceptMap(std::string t) {
_uiCollagen->playTimeUI(t);
_mp4Collagen->playTimeMp4(t);
}
定义中介对应处理的对象:
class ICollagen {
public:
//传递一个中介者
ICollagen(IMediator* m);
~ICollagen();
//播放
virtual void play(std::string time);
//加速
virtual void speedUp(int r);
//时间
virtual void playTime(std::string t);
protected:
IMediator* _meditor;
};
ICollagen::ICollagen(IMediator* m) {
_meditor = m;
}
ICollagen::~ICollagen() {
}
void ICollagen::play(std::string time) {
}
void ICollagen::speedUp(int r) {
}
void ICollagen::playTime(std::string t) {
}
定义具体的处理对象:
//界面
class UICollagen :public ICollagen {
public:
UICollagen(IMediator* m);
//播放
virtual void play(std::string time)override;
void playUI(std::string time);
//加速
virtual void speedUp(int r)override;
void speedUpUI(int r);
//时间同步
virtual void playTime(std::string t)override;
void playTimeUI(std::string t);
};
//图像绘制
class MapCollagen :public ICollagen {
public:
MapCollagen(IMediator* m);
//播放
virtual void play(std::string time)override;
void palyMap(std::string time);
//加速
virtual void speedUp(int r)override;
void speedUpMap(int r);
//时间同步
virtual void playTime(std::string t)override;
void playTimeMap(std::string t);
};
//声音绘制
class MP4Collagen :public ICollagen {
public:
MP4Collagen(IMediator* m);
//播放
virtual void play(std::string time)override;
void palyMp4();
//加速
virtual void speedUp(int r)override;
void speedUpMp4(int r);
//时间同步
virtual void playTime(std::string t)override;
void playTimeMp4(std::string t);
};
UICollagen::UICollagen(IMediator* m)
:ICollagen(m) {
}
void UICollagen::play(std::string time) {
_meditor->playExceptUI(time);
}
void UICollagen::speedUp(int r) {
_meditor->speedUpExceptUI(r);
}
void UICollagen::playTime(std::string t) {
_meditor->playTimeExceptUI(t);
}
void UICollagen::playUI(std::string time) {
printf("回放界面开始显示回放时间!\n");
}
void UICollagen::speedUpUI(int r) {
printf("回放界面跟新播放速率!\n");
}
void UICollagen::playTimeUI(std::string t) {
printf("UI显示当前时间:%s\n", t.c_str());
}
//
MapCollagen::MapCollagen(IMediator* m)
:ICollagen(m) {
}
void MapCollagen::play(std::string time) {
_meditor->playExceptMap(time);
}
void MapCollagen::speedUp(int r) {
_meditor->speedUpExceptMap(r);
}
void MapCollagen::playTime(std::string t) {
_meditor->playExceptMap(t);
}
void MapCollagen::palyMap(std::string time) {
printf("地图开始回放态势!\n");
}
void MapCollagen::speedUpMap(int r) {
printf("地图加速回放态势!\n");
}
void MapCollagen::playTimeMap(std::string t) {
printf("地图更新当前时间:%s!\n", t.c_str());
}
//
MP4Collagen::MP4Collagen(IMediator* m)
:ICollagen(m) {
}
void MP4Collagen::play(std::string time) {
_meditor->playExceptMP4(time);
}
void MP4Collagen::speedUp(int r) {
_meditor->speedUpExceptMP4(r);
}
void MP4Collagen::playTime(std::string t) {
_meditor->playTimeExceptMP4(t);
}
void MP4Collagen::palyMp4() {
printf("PM4开始播放!\n");
}
void MP4Collagen::speedUpMp4(int r) {
printf("PM4加速播放!\n");
}
void MP4Collagen::playTimeMp4(std::string t) {
printf("PM4设置当前播放时间:%s!\n", t.c_str());
}
已经定义完成了,看看客户端如何调用:
int main() {
IMediator* m = new MyMediator;
UICollagen* ui = new UICollagen(m);
MapCollagen* map = new MapCollagen(m);
MP4Collagen* mp4 = new MP4Collagen(m);
ui->playTime("10:10:10");
mp4->speedUp(2);
return 0;
}
运行一下:
中介者模式优点:
1.符合迪米特原则;
2.使原来多对多的关系,变成一对多的关系,结构更清晰。