1. 程式人生 > >【C++設計模式】命令模式

【C++設計模式】命令模式

#ifndef __COMMAND_H__
#define __COMMAND_H__

#include <iostream>
#include <list>

//命令模式(Command):將一個請求封裝成一個物件(Command物件),並賦予該物件一個執行介面。

//從而使你可用不同的請求對客戶進行引數化;對請求排隊或記錄請求日誌,以及支援可撤銷的操作。

//Command物件在執行命令時,並不一定自己切身做這件事,而是將請求轉發給另一個真正做這件事情的物件(Receiver物件),由Receiver物件最終完成請求操作。

//Command類,用來宣告執行操作的介面
class iCommand
{
public:
	virtual void execute() = 0;
};

//Receiver類,真正執行請求相關操作的介面,任何類都可能作為一個接收者。
class iReceiver
{
public:
	virtual void execute() = 0;
};

//播放音樂命令
class PlayCommand : public iCommand
{
public:
	PlayCommand(iReceiver* recv);

	virtual void execute();
private:
	iReceiver *m_recv;
};

//烹飪命令
class CookCommand : public iCommand
{
public:
	CookCommand(iReceiver* recv);

	virtual void execute();
private:
	iReceiver *m_recv;
};

//播放器
class MediaPlayer : public iReceiver
{
public:
	virtual void execute();
};

//廚師
class Chef : public iReceiver
{
public:
	virtual void execute();
};

//如果客戶端需要多種命令能夠按照某個佇列依次執行,我們需要把命令的執行者從客戶端中分離出來。
//引入一個物件叫排程者,Invoker類,來控制命令的佇列化和可撤銷操作等,對命令進行管理。
class Invoker
{
public:
	void AddCommand(iCommand* cmd);

	int  ExecuteCommand();

	void CancelCommand(iCommand *com);

	void RollbackCommand(iCommand *com);

private:	
	std::list<iCommand*> m_cmdlist;
	std::list<iCommand*> m_historycmdlist;
};

void TestCommand();

#endif

#include "Command.h"

PlayCommand::PlayCommand(iReceiver* recv) : m_recv(recv)
{

}

void PlayCommand::execute()
{
	m_recv->execute();
}

CookCommand::CookCommand(iReceiver* recv) : m_recv(recv)
{

}

void CookCommand::execute()
{
	m_recv->execute();
}

void MediaPlayer::execute()
{
	printf("start play music .\n");
}

void Chef::execute()
{
	printf("start cook .\n");
}

void Invoker::AddCommand(iCommand* cmd)
{
	m_cmdlist.push_back(cmd);
}

int Invoker::ExecuteCommand()
{
	if (!m_cmdlist.empty())
	{
		iCommand * cmd = NULL;

		cmd = m_cmdlist.front();

		cmd->execute();

		m_cmdlist.pop_front();

		m_historycmdlist.push_back(cmd);
	}

	return -1;
}

void Invoker::CancelCommand(iCommand *com)
{
	//遍歷命令佇列,找到命令並刪除
}

void Invoker::RollbackCommand(iCommand *com)
{
	//找到歷史命令,並執行狀態還原
}

void TestCommand()
{
	iReceiver *chef   = new Chef();
	iCommand *cookcmd = new CookCommand(chef);

	iReceiver *player = new MediaPlayer();
	iCommand *playcmd = new PlayCommand(player);

	Invoker *inv = new Invoker();

	inv->AddCommand(playcmd);

	inv->AddCommand(cookcmd);

	inv->ExecuteCommand();

	inv->ExecuteCommand();
}