多个对象互相调用中中介者设计模式的使用

C++对象之间的调用,可以通过对象+成员函数的方式实现,一般情况下,被调用的对象定义为成员变量,然后就可以被调用者进行调用了,这称为单向调用。

单向调用指的是对象之间调用方向,函数调用只能从调用者对象调用被调用者对象。

但是有时对象之间的调用也是互相的,也就是双向调用,调用者和被调用者没有明确的界限,有时需要对象A调用对象B的函数,有时需要对象B调用对象A的功能。对象之间的互相调用的也可以实现,在QT中一般通过信号槽的方式实现,对象A的信号关联对象B的槽函数,就实现了A对B的“调用”;对象B信号关联对象A的槽函数,就实现了B对A的“调用”。由于A和B使用了不同的信号和槽函数,所以也就不会出现调用“冲突”的情况。

场景:
一个关于GIS的回放软件:工人拿着GPS和音视频设备(录音笔或者视屏记录仪)出去办公,回来之后复盘今天的工作情况,需要一面在地图上回放航迹,观看行走的位置,一面观看视频,还有同时听取录音情况。同时要求这三者之间的同步播放、暂停、快进、慢进等。也许你觉得这个功能比较简单,可以实现。在地图界面上添加一个工具条,上面有控制按钮,当点击不同的按钮时航迹实现相应的功能,同时给视屏播放器或者音频播放器发送消息实现就可以了。

这只是其中的一个功能。

由于采用多屏播放器,不同的屏幕播放不同的界面,一个屏幕播放航迹,一个屏幕播放视频,一个屏幕播放音频。当观看其中一个屏幕的时候,在需要的时候要暂停或者快进等。比如在观看视频的时候,发现异常,只能在视频播放的界面暂停,同时在航迹回放的时候也要同步的暂停,音频播放器也要暂停。用户可以去同时观看航迹的位置;在听音频的时候,听到不对的地方,在音频界面可以暂停音频,同时在航迹播放和视频播放也需要暂停。

以上需要也就是说,我只要操作任意一个界面上的按钮,就可以同时控制其他界面的功能,它们之间就是相互之间的调用。其中一个播放器功能并不是自己开发的而是使用的第三方的播放器,需要通过发送消息的方式实现控制。

当三者之间有相互调用关系的时候,这里面的调用逻辑就是比较复杂了。当其中一个发出消息控制其他的界面,其他界面接收到消息后,进行相应的处理,包括按钮的点击事件。但是当鼠标点击按钮时,也会出现按钮的点击事件。这里面就需要一些逻辑控制了。

为了解耦接收到的消息和鼠标本身的按钮机制,可以把所有的需要控制的对象,包括GPS航迹回放界面、音频界面、视频界面击中起来进行管理。

每种控制界面都需要有相同的功能(播放、暂停、快进、快退等),把这些相同的功能提取出来封装成一个基类:

//态势同步操作
class INTERFACEIMPL_EXPORT ISynchPlay {
public:
	ISynchPlay();
	~ISynchPlay();

	//播放
	virtual void synchPlay(void* runningTime, double rate = 1.0);
	//运行时开始播放-态势正在运行
	virtual void synchRunStartPlay(void* runningTime);
	//暂停
	virtual void synchPause(void* runningTime);
	//跳到某时间
	virtual void synchJumpTo(void* runningTime);
	//下一秒
	virtual void synchForwardFrame(void* runningTime);
	//上一秒
	virtual void synchBackwardFrame(void* runningTime);
	//加速
	virtual void synchAccelerateRate(double rate);
	//减速
	virtual void synchDecelerateRate(double rate);
};
ISynchPlay::ISynchPlay() {
}


ISynchPlay::~ISynchPlay() {
}

void ISynchPlay::synchPlay(void* runningTime, double rate) {

}

void ISynchPlay::synchRunStartPlay(void* runningTime) {

}

void ISynchPlay::synchPause(void* runningTime) {

}

void ISynchPlay::synchJumpTo(void* runningTime) {

}

void ISynchPlay::synchForwardFrame(void* runningTime) {

}

void ISynchPlay::synchBackwardFrame(void* runningTime) {

}

void ISynchPlay::synchAccelerateRate(double rate) {

}

void ISynchPlay::synchDecelerateRate(double rate) {

}

然后定义一个共有对象基类,用来表示控制界面:

class INTERFACEIMPL_EXPORT IMediationObj:public ISynchPlay {
public:
	IMediationObj();
	~IMediationObj();

protected:
};

然后就是三个功能模块分别继承这个对象基类,并且实现相应的功能。

为了便于管理这些对象需要,把这些对象保存起来统一进行管理:

class INTERFACEIMPL_EXPORT MediaObjManager {
private:
	MediaObjManager();
	static MediaObjManager*_instance;
public:
	static MediaObjManager*getInstance();

	void saveMediaObj(MediaObjType t, IMediationObj* obj);
	IMediationObj* loadMediaObj(MediaObjType t);

	std::map<MediaObjType, IMediationObj*>&getMediaObj() {
		return _mediaObj;
	}

private:
	std::map<MediaObjType, IMediationObj*> _mediaObj;
};
MediaObjManager::MediaObjManager() {

}

MediaObjManager* MediaObjManager::_instance = new MediaObjManager;
MediaObjManager* MediaObjManager::getInstance() {
	return _instance;
}

void MediaObjManager::saveMediaObj(MediaObjType t, IMediationObj* obj) {
	_mediaObj[t] = obj;
}

IMediationObj* MediaObjManager::loadMediaObj(MediaObjType t) {
	return _mediaObj[t];
}

不同的界面定义不同标志已示区别:


enum MediaObjType {
	MEDIAOBJ_UI,//回放界面
	MEDIAOBJ_MAP,//地图GPS
	MEDIAOBJ_MP4,//MP4播放
	MEDIAOBJ_AUDIO,//音频播放
};

定义三者同步播放的管理器:

class VIDEOREPLAY_EXPORT PlayMediator  {

private:
	PlayMediator();
	static PlayMediator* _instance;
public:
	~PlayMediator();
	static PlayMediator* getInstance();

	//播放
	void synchPlay(MediaObjType objType, void* runningTime, double rate = 1.0);
	//开始同步播放
	void synchRunStartPlay(MediaObjType objType, void* runningTime);
	//暂停
	void synchPause(MediaObjType objType, void* runningTime);
	//跳转
	void synchJumpTo(MediaObjType objType, void* runningTime);
	//向前
	void synchForwardFrame(MediaObjType objType, void* runningTime);
	//向后
	void synchBackwardFrame(MediaObjType objType, void* runningTime);
	//加速
	void synchAccelerateRate(MediaObjType objType, double rate);
	//减速
	void synchDecelerateRate(MediaObjType objType, double rate);

};
PlayMediator* PlayMediator::_instance = new PlayMediator;

PlayMediator::PlayMediator() {
}

PlayMediator::~PlayMediator() {
}

PlayMediator* PlayMediator::getInstance() {
	return _instance;
}

void PlayMediator::synchPlay(MediaObjType objType, void* runningTime, double rate) {
	std::map<MediaObjType, IMediationObj*>&mediaObj = MeObjMgr()->getMediaObj();
	int num = mediaObj.size();
	for (auto m: mediaObj){
		if (m.first != objType) {
			m.second->synchPlay(runningTime);
		}
		
	}
}

void PlayMediator::synchRunStartPlay(MediaObjType objType, void* runningTime) {
	std::map<MediaObjType, IMediationObj*>&mediaObj = MeObjMgr()->getMediaObj();
	int num = mediaObj.size();
	for (auto m : mediaObj) {
		if (m.first != objType) {
			m.second->synchRunStartPlay(runningTime);
		}
	}
}

void PlayMediator::synchPause(MediaObjType objType, void* runningTime) {
	std::map<MediaObjType, IMediationObj*>&mediaObj = MeObjMgr()->getMediaObj();
	int num = mediaObj.size();
	for (auto m : mediaObj) {
		if (m.first != objType) {
			m.second->synchPause(runningTime);
		}
	}
}

void PlayMediator::synchJumpTo(MediaObjType objType, void* runningTime) {
	std::map<MediaObjType, IMediationObj*>&mediaObj = MeObjMgr()->getMediaObj();
	int num = mediaObj.size();
	for (auto m : mediaObj) {
		if (m.first != objType) {
			m.second->synchJumpTo(runningTime);
		}
	}
}

void PlayMediator::synchForwardFrame(MediaObjType objType, void* runningTime) {
	std::map<MediaObjType, IMediationObj*>&mediaObj = MeObjMgr()->getMediaObj();
	int num = mediaObj.size();
	for (auto m : mediaObj) {
		if (m.first != objType) {
			m.second->synchForwardFrame(runningTime);
		}
	}
}

void PlayMediator::synchBackwardFrame(MediaObjType objType, void* runningTime) {
	std::map<MediaObjType, IMediationObj*>&mediaObj = MeObjMgr()->getMediaObj();
	int num = mediaObj.size();
	for (auto m : mediaObj) {
		if (m.first != objType) {
			m.second->synchBackwardFrame(runningTime);
		}
	}
}

void PlayMediator::synchAccelerateRate(MediaObjType objType, double rate) {
	std::map<MediaObjType, IMediationObj*>&mediaObj = MeObjMgr()->getMediaObj();
	int num = mediaObj.size();
	for (auto m : mediaObj) {
		if (m.first != objType) {
			m.second->synchAccelerateRate(rate);
		}
	}
}

void PlayMediator::synchDecelerateRate(MediaObjType objType, double rate) {
	std::map<MediaObjType, IMediationObj*>&mediaObj = MeObjMgr()->getMediaObj();
	int num = mediaObj.size();
	for (auto m : mediaObj) {
		if (m.first != objType) {
			m.second->synchDecelerateRate(rate);
		}
	}
}

以上就可以实现了三者之间只要任意控制其中的一个界面,其他的界面也就可以同步的实现了!

这里面有中介者?

有的,对象管理器就是一个中介MediaObjManager,当其中的一个界面需要同步娶她的界面的时候,不必直接控制其他的界面,而是使用这个中介者就可以进行控制了,减少了类之间的耦合。

aaa

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wb175208

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

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

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

打赏作者

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

抵扣说明:

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

余额充值