一,概述
定义:命令模式将一个请求或者操作封装到一个命令对象中。允许系统使用不同的请求将客户端参数化,对请求排队或者记录请求日志,提供命令的撤销,恢复能力
优点:
1 命令模式使新的命令很容易被加入
2 允许接受请求方否决请求
3 可较容易地设计一个命令队列
4 可以实现对请求的Undo,Redo
5 可以将命令计入日志
二,示例
两个人 去吃烧烤,先路过一个烧烤摊,人多管理比较混乱,命令请求者跟命令实施者“紧耦合”。
人太对,没吃,然后去烧烤店,遇到了经典的命令模式:服务生负责记录命令,传递命令。厨师负责执行命令。顾客则发出命令
1)烧烤摊代码
#include <iostream>
using namespace std;
//烤肉串者
class Barbecuer
{
//烤羊肉
public:
void BakeMutton()
{
cout<<"烤羊肉串!"<<endl;
}
//烤鸡翅
void BakeChickenWing()
{
cout<<"烤鸡翅!"<<endl;
}
};
int main()
{
Barbecuer *boy = new Barbecuer();
boy->BakeMutton();
boy->BakeMutton();
boy->BakeMutton();
boy->BakeChickenWing();
boy->BakeMutton();
boy->BakeMutton();
boy->BakeChickenWing();
}
2)烧烤店(第一版)
缺点:客户点一个菜,服务员通知一下(不符合实际)。应该点菜完成后一次性通知
如果某一个菜没有了,不应该客户判断,应该服务员判断
客户点菜需要记录日志,以备结账使用。
#include <iostream>
using namespace std;
//烤肉串者
class Barbecuer//命令执行者
{
public:
void BakeMutton()
{
cout<<"烤羊肉串!"<<endl;
}
void BakeChickenWing()
{
cout<<"烤鸡翅!"<<endl;
}
};
//抽象命令
class Command//声明执行的接口
{
protected:
Barbecuer *receiver;
public:
Command(Barbecuer *receiver)
{
this->receiver = receiver;
}
//执行命令
virtual void ExcuteCommand()=0;
};
//服务员
class Waiter //Invoker类
{
private:
Command *command;
//设置订单
public:
void SetOrder(Command *command)
{
this->command = command;
}
//通知执行
void Notify()
{
command->ExcuteCommand();
}
};
//烤羊肉串命令
class BakeMuttonCommand :public Command
{
public:
BakeMuttonCommand(Barbecuer *receiver)
: Command(receiver)
{ }
void ExcuteCommand()
{
receiver->BakeMutton();
}
};
//烤鸡翅命令
class BakeChickenWingCommand :public Command
{
public:
BakeChickenWingCommand(Barbecuer *receiver)
: Command(receiver)
{ }
void ExcuteCommand()
{
receiver->BakeChickenWing();
}
};
int main()
{
//开店前的准备
Barbecuer *boy = new Barbecuer();
Command *bakeMuttonCommand1 = new BakeMuttonCommand(boy);// 烤羊肉
Command *bakeMuttonCommand2 = new BakeMuttonCommand(boy);
Command *bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);//烤鸡翅
Waiter *girl = new Waiter();
//开门营业
girl->SetOrder(bakeMuttonCommand1);
girl->Notify();
girl->SetOrder(bakeMuttonCommand2);
girl->Notify();
girl->SetOrder(bakeChickenWingCommand1);
girl->Notify();
}
3)烧烤店(松耦合升级版)(C#)
static void Main(string[] args)
{
//开店前的准备
Barbecuer boy = new Barbecuer();
Command bakeMuttonCommand1 = new BakeMuttonCommand(boy);
Command bakeMuttonCommand2 = new BakeMuttonCommand(boy);
Command bakeChickenWingCommand1 = new BakeChickenWingCommand(boy);
Waiter girl = new Waiter();
//开门营业 顾客点菜
girl.SetOrder(bakeMuttonCommand1);
girl.SetOrder(bakeMuttonCommand2);
girl.SetOrder(bakeChickenWingCommand1);
//点菜完闭,通知厨房
girl.Notify();
Console.Read();
}
}
//服务员
public class Waiter
{
private IList<Command> orders = new List<Command>();
//设置订单
public void SetOrder(Command command)
{
if (command.ToString() == "命令模式.BakeChickenWingCommand")
{
Console.WriteLine("服务员:鸡翅没有了,请点别的烧烤。");
}
else
{
orders.Add(command);
Console.WriteLine("增加订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString());
}
}
//取消订单
public void CancelOrder(Command command)
{
orders.Remove(command);
Console.WriteLine("取消订单:" + command.ToString() + " 时间:" + DateTime.Now.ToString());
}
//通知全部执行
public void Notify()
{
foreach (Command cmd in orders)
{
cmd.ExcuteCommand();
}
}
}
//抽象命令
public abstract class Command
{
protected Barbecuer receiver;
public Command(Barbecuer receiver)
{
this.receiver = receiver;
}
//执行命令
abstract public void ExcuteCommand();
}
//烤羊肉串命令
class BakeMuttonCommand : Command
{
public BakeMuttonCommand(Barbecuer receiver)
: base(receiver)
{ }
public override void ExcuteCommand()
{
receiver.BakeMutton();
}
}
//烤鸡翅命令
class BakeChickenWingCommand : Command
{
public BakeChickenWingCommand(Barbecuer receiver)
: base(receiver)
{ }
public override void ExcuteCommand()
{
receiver.BakeChickenWing();
}
}
//烤肉串者
public class Barbecuer
{
public void BakeMutton()
{
Console.WriteLine("烤羊肉串!");
}
public void BakeChickenWing()
{
Console.WriteLine("烤鸡翅!");
}
}
三,命令模式基本代码构成
#include <iostream>
using namespace std;
class Receiver//执行命令类
{
public:
void Action()
{
cout<<"执行请求!"<<endl;
}
};
class Command //声明执行操作的接口
{
protected:
Receiver *receiver;
public:
Command(Receiver *receiver)
{
this->receiver = receiver;
}
virtual void Execute()=0;
};
class Invoker//要求该命令执行这个请求
{
private:
Command *command;
public:
void SetCommand(Command *command)
{
this->command = command;
}
void ExecuteCommand()
{
command->Execute();
}
};
class ConcreteCommand :public Command //将一个接收者对象绑定于一个动作
{
public:
ConcreteCommand(Receiver *receiver):Command(receiver)
{ }
void Execute() //实现命令接口
{
receiver->Action();
}
};
int main()
{
Receiver *r = new Receiver();//命令的真正执行类 (后台厨师)
Command *c = new ConcreteCommand(r);//将命令绑定到 命令执行者 (顾客)
Invoker *i = new Invoker();//要求命令执行者执行命令(记账单的小生)
// Set and execute command
i->SetCommand(c);
i->ExecuteCommand();
system("pause");
}