定义:
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
在软件系统中,【行为请求者】与【行为实现者】通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做等处理时,这种无法抵御变化的紧耦合的设计就不太合适。命令模式就是将请求和实现解耦,以便能方便的实现对行为进行记录、撤销或重做等处理。
结构图:
代码(模拟烧烤店):
//Command类(抽象命令类(菜单))
class Command
{
public:
//声明命令执行者(烤串师傅)
Barbecuer cReceiver;
//定义命令
void ExcuteCommand() = 0;
}
//Command实现类(具体命令类:烤羊肉串命令)
class MuttonCommand : Command
{
//调用指定的接收者(烤串师傅)执行命令(烤羊肉串)
public:
void ExcuteCommand()
{
cReceiver.Mutton();
}
}
//Command实现类(具体命令类:烤鸡命令)
class ChickenCommand : Command
{
//调用指定的接收者(烤串师傅)执行命令(烤鸡)
public:
void ExcuteCommand()
{
cReceiver.Chicken();
}
}
//Invoker类(服务员类、请求类,方便理解)
class Waiter
{
Private IList<Command> order;//存放具体命令的容器(客户单)
public:
//下单
void SetOrder(const Command &cCommand)
{
Order.add(cCommand);
。。。;
}
//取消订单
void CancelOrder(const Command &cCommand)
{
Order.Remove(cCommand);
。。。;
}
//通知执行
void Notify()
{
foreach(command cmd in orders)
cmd.ExcuteCommand();
}
}
//Recevie实现类(烧烤师傅)
class Barbecuer
{
public:
//烤羊肉串
void Mutton()
{
。。。;
}
//烤鸡
void Chicken()
{
。。。;
}
}
//客户端
//开店前准备
Barbecuer* cBarbecuer = new Barbecuer();//创建一个烧烤师傅
Waiter* cWaiter = new Waiter ();//创建一个服务员
Command* cMuttonCommand = new MuttonCommand(cBarbecuer)//给命令设置执行者
Command* cChickenCommand = new ChickenCommand(cBarbecuer);//给命令设置执行者
//营业下单
cWaiter.SetOrder(cMuttonCommand);//点一个羊肉串
cWaiter.SetOrder(cChickenCommand);//点一个鸡肉串
cWaiter.CancelOrder(cMuttonCommand);//取消羊肉串
cWaiter.Notify();//下单完成,通知执行
//如果接收者不止一个类,只需要在Command类中声明不同接收者类,在具体命令中调用执行方法就行了。接收者可以是任何类。
使用时机:
系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作,可以考虑使用命令模式;
优点:
1、比较容易的设计一个命令队列;
2、可以比较容易的的将命令记入日志、对请求撤销和重做;
3、很容易新加具体命令类;
4、请求和执行分离,解耦合。
缺点:更多的类,使程序更加复杂。
原文:https://www.cnblogs.com/haosk/p/13548875.html