设计模式实现(十九)---命令模式(Command)

本文介绍了软件设计中的命令模式,包括其核心概念、实现方式及其应用场景。通过具体的代码示例,展示了命令模式如何帮助开发者更好地组织代码,并支持撤销操作等功能。

命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。


//Receiver类,知道如何实施与执行一个与请求相关的操作,任何类都可能作为一个接收者。
class Receiver
{
public:
	void Action()
	{
		printf("执行请求!");
	}
};

//Command类,用来声明执行操作的接口。
class Command
{
protected:
	Receiver *receiver;
public:
	Command(Receiver *receiver)
	{
		this->receiver = receiver;
	}
	virtual void Execute() = 0;
};

//具体Command类,将一个接收者对象绑定于一个动作,调用接收者相应的操作,以实现Execute
class ConcreteCommand : public Command
{
public:
	ConcreteCommand(Receiver *reciver) : Command(reciver){}
public:
	void Execute()
	{
		receiver->Action();
	}
};

//Invoker类,要求该命令执行这个请求
class Invoker
{
private:
	//list<Command> commands;			//可以是一组,见例子
	Command *command;
public:
	void SetCommand(Command *command)
	{
		this->command = command;
	}
	void ExecuteCommand()
	{
		command->Execute();
	}
};

//客户端代码,创建一个具体命令对象并设定它的接收者
int main()
{
	Receiver r;
	ConcreteCommand cc(&r);
	Invoker i;
	i.SetCommand(&cc);
	i.ExecuteCommand();
	return 1;
}
命令模式能用来做什么?

第一:它能较容易的设计一个命令队列;

第二:在需要的情况下,可以比较容易的将命令计入日志。

第三:允许接收请求的一方决定是否要否决请求。

第四:可以容易地实现对请求的撤销和重做;

第五:由于加进新的具体命令类不影响其他的类,因为增加新的具体命令类很容易。

命令模式的关键优点是:把请求一个操作的对象与指导怎么执行一个操作的对象分割开。

敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般就不要着急去实现它,事实上,在需要的时候通过重构实现这个模式并不困难,只有在真正需要如撤销/恢复操作功能时,把原来的代码重构为命令模式才有意义。

下面例子体现了命令模式的作用及特点:


#include <iostream>
#include <list>
#include <string>
#include <time.h>
//#include<stdio.h>
using namespace std;
//路边烤肉的例子,服务员是Invoker,烤肉者是Receiver

//烤肉者类
class Barbecuer
{
public:
	//烤羊肉
	void BakeMutton()
	{
		cout << "烤羊肉串!" << endl;
	}
	void BakeChickenWing()
	{
		cout << "烤鸡翅!" << endl;
	}
};

//抽象命令类
//Command类,用来声明执行操作的接口。
class Command
{
public:
	string instruction;
protected:
	
	Barbecuer *receiver;
public:
	Command(Barbecuer *receiver)
	{
		this->receiver = receiver;
	}
	virtual void Execute() = 0;
};

//具体Command类,烤鸡翅命令
class BakeChickenWingCommand : public Command
{
public:
	
	BakeChickenWingCommand(Barbecuer *reciver) : Command(reciver){instruction = "烤鸡翅";}
public:
	void Execute()
	{
		receiver->BakeChickenWing();
	}
};

//具体Command类,烤羊肉串命令
class BakeMuttonCommand : public Command
{
public:
	BakeMuttonCommand(Barbecuer *reciver) : Command(reciver){instruction = "烤羊肉";}
public:
	void Execute()
	{
		receiver->BakeMutton();
	}
};

//服务员类,Invoker类
class Waiter
{
private:
	list<Command *> commands;
public:
	//添加订单,因为订单不可能只点一样菜,所以是list
	void SetOrder(Command *command)
	{
		if(command->instruction == "烤鸡翅")
		{
			cout << "服务员:没有鸡翅了,请点别的烧烤。"<<endl;
		}
		else
		{
			commands.push_back(command);
			time_t t;
			time(&t);
			cout << "增加了订单:" << command->instruction << " 时间:"<<ctime(&t)<<endl;
		}
	}
	void CancelOrder(Command *command)
	{
		commands.remove(command);
		time_t t;
		time(&t);
		cout << "取消了了订单:" << command->instruction << " 时间:"<<ctime(&t)<<endl;
	}

	//通知全部执行
	void Notify()
	{
		list<Command *>::iterator iter = commands.begin();
		for(;iter!=commands.end();iter++)
		{
			(*iter)->Execute();
		}
	}
};

//客户端
int main()
{
	//开店前准备
	Barbecuer boy;
	BakeMuttonCommand bakeMttonCommand1(&boy);
	BakeMuttonCommand bakeMttonCommand2(&boy);
	BakeChickenWingCommand bakeChickenWingCommand(&boy);
	Waiter girl;
	
	//顾客点餐
	girl.SetOrder(&bakeMttonCommand1);
	girl.SetOrder(&bakeMttonCommand2);
	girl.SetOrder(&bakeChickenWingCommand);
	
	//点菜完毕,通知厨房
	girl.Notify();

	//取消羊肉1
	girl.CancelOrder(&bakeMttonCommand1);
	return 1;

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值