Command Pattern -- 命令模式原理及实现(C++)
主要参考《大话设计模式》和《设计模式:可复用面向对象软件的基础》两本书。本文介绍命令模式的实现。

What it is:Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。在OOP中,一切都是对象,将请求封装成对象,符合OOP的设计思想,当将客户的单个请求封装成对象以后,我们就可以对这个请求存储更多的信息,使请求拥有更多的能力;命令模式同样能够把请求发送者和接收者解耦,使得命令发送者不用去关心请求将以何种方式被处理。

Command:声明执行操作的接口;
ConcreteCommand:将一个接收者对象绑定于一个动作,之后,调用接收者相应的操作,以实现Execute来完成相应的命令;
Client:创建一个具体命令对象,但是并没有设定它的接收者;
Invoker:要求该命令执行这个请求;
Receiver:知道如何实施与执行一个请求相关的操作,任何类都可能作为一个接收者。
以上这些对象是按照下面的方式进行协作的:
1.Client创建一个ConcreteCommand命令对象,并指定它的Receiver对象;
2.Invoker对象存储该ConcreteCommand对象;
3.该Invoker通过调用Command对象的Execute操作来提交一个请求。如果这个命令请求是可以撤销的,ConcreteCommand就执行Execute操作之前存储当前状态以用于取消该命令请求;
4.ConcreteCommand对象调用Receiver的一些操作以执行该请求。
具体事例:
我们去餐厅吃饭,我们是通过服务员来点菜,具体是谁来做这些菜和他们什么时候完成的这些菜,其实我们都不知道。抽象之,我们是“菜单请求者”,厨师是“菜单实现者”,2者之间是松耦合的,我们对这些菜的其他一些请求比如“撤销,重做”等,我们也不知道是谁在做。其实这就是本文要说的Command模式。将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤消的操作。[GOF 《设计模式》]
UML图如下:

具体代码C++代码实现:
#include <iostream>
#include <string>
#include <vector>
using namespace std; #define SAFE_DELETE(p) if (p) { delete p; p = NULL; }
/*烤肉师傅类,只负责烤串工作*/
class Barbecuer
{
public:
void BakeMutton(){cout<<"Bake mutton"<<endl;}
void BakeChickenWing(){cout<<"Bake ChickenWing"<<endl;}
}; /*抽象命令类:是执行具体操作的接口*/
class Command
{
public:
Command(){}
Command(Barbecuer *receiver):p_receiver(receiver){}
virtual void ExecuteCommand() = ; //执行命令
protected:
Barbecuer *p_receiver;
}; /*具体命令类:烤羊肉串命令*/
class BakeMuttonCommand:public Command
{
public:
BakeMuttonCommand(Barbecuer *receiver){p_receiver = receiver;}
void ExecuteCommand(){p_receiver->BakeMutton();}
}; /*具体命令类:烤鸡翅串命令*/
class BakeChickenWingCommand:public Command
{
public:
BakeChickenWingCommand(Barbecuer *receiver){p_receiver = receiver;}
void ExecuteCommand()
{p_receiver->BakeChickenWing();}
}; /*服务员类*/
class Waiter
{
public:
void SetOrder(Command *command);
void Notify();
private:
vector<Command *>p_commandList; //这里相当于一个命令对象队列
}; void Waiter::SetOrder(Command *command)
{
p_commandList.push_back(command);
cout << "增加烤肉命令" << endl;
} void Waiter::Notify()
{
vector<Command*>::iterator i;
for(i = p_commandList.begin(); i != p_commandList.end(); ++ i)
(*i)->ExecuteCommand();
} int main(int argc, char *argv[])
{
//生成烤肉师傅、服务员、订单对象
Barbecuer *p_cook = new Barbecuer();
Command *p_mutton = new BakeMuttonCommand(p_cook);
Command *p_chickenwing = new BakeChickenWingCommand(p_cook);
Waiter *p_waiter = new Waiter(); //将订单对象推送到命令队列
p_waiter->SetOrder(p_mutton);
p_waiter->SetOrder(p_chickenwing); //服务员通知烤肉师傅具体订单
p_waiter->Notify(); SAFE_DELETE(p_cook);
SAFE_DELETE(p_mutton);
SAFE_DELETE(p_chickenwing);
SAFE_DELETE(p_waiter); return ;
}
Command Pattern -- 命令模式原理及实现(C++)的更多相关文章
- Command Pattern 命令模式
定义: 命令模式将‘请求’封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作. 类图 如上图所示:Command类是用来声明执行操作的接口:ConcreteCom ...
- (Command Pattern)命令模式
定义 将“请求”封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 结构图: 命令模式的角色划分: Reciever(命令的接收者):接收命令,并知道如何进行必 ...
- [Design Pattern] Command Pattern 命令模式
发现公司的代码好像有用到 Command Pattern,回顾重温下. Command Pattern 的类图结构如下: 参考 <Head First Design Patterns(英文版)& ...
- Design Pattern - 命令模式
一般执行一个操作的过程, 创建对象, 并调用对象的函数, 函数执行, 返回 比如下面的类图, client直接调用Receiver.action 而命令模式, 抽象出command对象, 并在comm ...
- State Pattern -- 状态模式原理及实现(C++)
主要参考<大话设计模式>和<设计模式:可复用面向对象软件的基础>两本书.本文介绍命令模式的实现. 问题出发点 在实际开发中,我们经常会遇到这种情况:一个对象有多种状态,在每一个 ...
- c#设计模式系列:命令模式(Command Pattern)
引言 命令模式,我感觉"命令"就是任务,执行了命令就完成了一个任务.或者说,命令是任务,我们再从这个名字上并不知道命令的发出者和接受者分别是谁,为什么呢?因为我们并不关心他们是谁, ...
- 命令模式(Command)
命令模式(Command) 命令模式很好理解,举个例子,司令员下令让士兵去干件事情,从整个事情的角度来考虑,司令员的作用是,发出口令,口令经过传递,传到了士兵耳朵里,士兵去执行.这个过程好在,三者相互 ...
- Java设计模式の命令模式
意图: 将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化:对请求排队或记录日志,以及支持可撤销的操作 动机: 将”发出请求的对象”和”接收与执行这些请求的对象”分隔开来. 效果: 1).c ...
- js命令模式
命令模式(Command),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 从命令模式的结构图可以看出,它涉及到五个角色,它们分别是 ...
随机推荐
- cxf构建webservice的两种方式
一.简介 对于基于soap传输协议的webservice有两种开发模式,代码优先和契约优先的模式.代码优先的模式是通过编写服务器端的代码,使用代码生成wsdl:契约优先模式首先编写wsdl,再通过ws ...
- Load xlsx in a folder to RDBMS table with Talend
Step 1 . Use tFileList component to get the file list. And set proper property. Step 2. Use tFileInp ...
- Hive remote install mode (mysql) step by step
Prerequisite: Hadoop cluster is avalable; Mysql installed on namenode; Step1: download the latest hi ...
- PHP采集程序中的常用函数
- [转]关于负margin在页面中布局的应用
本文转载自:http://www.cnblogs.com/jscode/archive/2012/08/28/2660078.html. 今天再写一个布局的时候用到一个margin-top是负值的情况 ...
- ACdream OJ 1099 瑶瑶的第K大 --分治+IO优化
这题其实就是一个求数组中第K大数的问题,用快速排序的思想可以解决.结果一路超时..原来要加输入输出优化,具体优化见代码. 顺便把求数组中第K大数和求数组中第K小数的求法给出来. 代码: /* * th ...
- nginx 一二事(3) - 反向代理以及负载均衡
先来说说正向代理 就是普通的代理,记得高中年代偷跑去网吧是要办卡的 题外话: 就是这货...相信很多80同龄人都有吧... 回到正题,那正向代理就不让你直接访问网络,而需要登录一下网吧的某个系统 ...
- for循环的三种写法
第一种写法 传统的方法,遍历数组 String[] arr = { "amy", "heinrich", "cindy", "g ...
- table标签去除默认边框
table去除默认边框 1.在没有出去默认边框时,改变底部颜色,依然显示1px左右的白色边框 2.为table 加上 border="0" cellpadding="0& ...
- 部署Zipkin分布式性能追踪日志系统的操作记录
Zipkin是Twitter的一个开源项目,是一个致力于收集Twitter所有服务的监控数据的分布式跟踪系统,它提供了收集数据,和查询数据两大接口服务. 部署Zipkin环境的操作记录:部署Zipki ...