欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

中介者模式的应用之用电脑播放电影

程序员文章站 2022-05-26 08:40:19
...
思考中介者模式

(1)中介者模式的本质封装交互。中介者的目的,就是用来封装多个对象的交互,这些交互的处理多在中介者对象里面实现。只要是实现封装对象之间的交互功能,就可用中介者模式,而不必过于拘泥于中介者模式本身的结构。

(2)需要Mediator接口吗

  这取决于是否会提供多个不同的中介者实现。如果中介者实现只有一个的话,而且预计中也没有扩展的需求,那就可以不定义Mediator接口。如果中介者实现不只一个,或者预计有扩展的要求,那么就需要定义Mediator接口。让各个同事类来面向中介者接口编程。

(3)同事关系

  在标准的中介者模式中,将使用中介者对象来交互的那些对象称为同事类,在中介者模式中要求这些类都要继承相同的类,也就是说这些对象从某个角度来讲是同一个类型,算是兄弟对象。

(4)同事和中介者的关系

  ①当一个同事对象发生了改变,需要主动通知中介者,让中介者去处理与其他同事对象相关的交互。

  ②同事对象需要知道中介者对象是谁,反过来,中介者对象也需要知道相关的同事对象,这样才能与同事对象进行交互。

  ③中介者对象与同事对象之间是相互依赖的。

(5)如何实现同事和中介者的通信

  ①同事类持有中介者对象,可以通过Mediator接口中定义一个特殊的通知接口(如changed),并把this当做参数传入,这样在中介者对象里面,就可以去获取这个同事对象的实例或当中的数据了。中介者对象里面记录着各个同事,会根据从changed接口中传入来的对象,判断下一步的动作。

  ②另一种实现方式可以采用观察者模式,把Mediator实现成为观察者,而各个同事类实现成为Subject,这样同事类发生了改变,会通知Mediator。Mediator在接到通知的以后,会与相应的同事对象进行交互。

【编程实验】用电脑看电影

中介者模式的应用之用电脑播放电影


//行为模式——中介者模式
//场景:使用电脑来看电影
//中介者:主板
//同事类:CPU、内存、光驱、显卡、声卡等

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class CHardware;//前向声明

//*******************************************抽象中介者**************************************
//抽象中介者
class CAbsMediator{
public:
	//同事对象在自身改变的时候调用这个接口来通知中介者
	virtual void Changed(CHardware* hardware) = 0;
};
//*******************************************抽象同事类**************************************
//抽象同事类
class CHardware{
protected:
	CAbsMediator* pMediator;
public:
	CHardware(CAbsMediator* mediator){pMediator = mediator;}
	//获取当前同事类对应的中介者对象
	CAbsMediator& GetMediator(){return *pMediator;}
};

//具体的同事类:光驱
class CCdDrv : public CHardware{
private:
	string strDat;
public:
	CCdDrv(CAbsMediator* mediator) : CHardware(mediator){}
	void ReadCd(){//读取光盘
		//逗号前是视频显示的数据,逗号后是声音
		strDat = "设计模式,值得好好研究";
		//通知中介者(主板),自己的状态发生了改变
		pMediator->Changed(this);
	}
	string& GetDat(){return strDat;}
};


//具体的同事类:CPU
class CCpu : public CHardware{
private:
	string strVideo;//分解出来的视频数据
	string strSound;//分解出来的声音数据
public:
	CCpu(CAbsMediator* mediator) : CHardware(mediator){}
	string& GetVideo(){return strVideo;}
	string& GetSound(){return strSound;}
	void DispartData(string data){//处理数据,把数据分成音频和视频数据
		int iPos = data.find(",");
		strVideo = data.substr(0, iPos);
		strSound = data.substr(iPos+1, data.length()-iPos);
		//通知主板,CPU的工作完成
		pMediator->Changed(this);
	}
};

//具体的同事类:显卡类
class CVideoCard : public CHardware{
private:
	string strVideo;//被显示的数据
public:
	CVideoCard(CAbsMediator* mediator) : CHardware(mediator){}
	void DispVideo(string data){
		cout << "您正在观看的是:" << data << endl;
	}
};

//具体的同事类:声卡类
class CSoundCard : public CHardware{
private:
	string strSound;//被播放的声音数据
public:
	CSoundCard(CAbsMediator* mediator) : CHardware(mediator){}
	void DispSound(string data){//显示数据
		cout << "画外音:" << data << endl;
	}
};

//*************************************具体中介者****************
//主板类
class CMainBoard : CAbsMediator{
private:
	CCdDrv* pCdDrv;
	CCpu* pCpu;
	CVideoCard* pVc;
	CSoundCard* pSc;
public:
	CMainBoard()
	{
		pCdDrv = new CCdDrv(this);
		pCpu = new CCpu(this);
		pVc = new CVideoCard(this);
		pSc = new CSoundCard(this);
	}
	~CMainBoard()
	{
		delete pCdDrv; pCdDrv = NULL;
		delete pCpu; pCpu = NULL;
		delete pVc; pVc = NULL;
		delete pSc; pSc = NULL;
	}
	CCdDrv* GetCd(){return pCdDrv;}
	//处理光驱读取数据以后与其他对象的交互
	void CdDrvReadDat(CCdDrv* cd){
		//1.获取光驱读取的数据
		string strData = cd->GetDat();
		//2.把这些数据传给CPU进行处理
		pCpu->DispartData(strData);
	}
	//CPU处理完数据后与其他对象的交互
	void CpuParseDat(CCpu* cpu){
		//1.先取出CPU处理后的数据
		string strVideo = cpu->GetVideo();
		string strSound = cpu->GetSound();
		//2. 把数据传递给显卡和声卡展示出来
		pVc->DispVideo(strVideo);
		pSc->DispSound(strSound);
	}
	//接收通知
	void Changed(CHardware* hardware){
		if(hardware == pCdDrv)				CdDrvReadDat(pCdDrv);
		else if(hardware == pCpu)			CpuParseDat(pCpu);
	}
};


void WatchFilm()
{
	CMainBoard oMainBoard;
	//开始看电影,把光盘放入光驱,光驱开始读盘
	oMainBoard.GetCd()->ReadCd();
}