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),将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 从命令模式的结构图可以看出,它涉及到五个角色,它们分别是 ...
随机推荐
- 烂泥:【解决】Ubuntu下使用SSH连接centos系统很慢
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 这几天在Ubuntu下使用SSH连接centos系统,发现连接很慢.建议一个连接大约需要30s.很是坑爹,如下: 后来查询相关资料,发现这个是Ubunt ...
- Linux系统命令查询软件包
转载自:http://blog.chinaunix.net/uid-346158-id-2131252.html,http://www.jb51.net/os/RedHat/1102.html, 一. ...
- linux安装hadoop 1.2.1
我的服务器里面会装很多东西,所以我在跟目录下面建立了个doc文档文件夹 1.创建存放软件的doc文件夹 mkdir doc 2.进去doc文件夹进行下载hadoop-1.2.1资源包或者到我的百度云下 ...
- Python pip – error: invalid command ‘bdist_wheel’
原文@http://software-engineer.gatsbylee.com/python-pip-error-invalid-command-bdist_wheel/ Python pip – ...
- [转]EXCEL如何使用动态公式
本文转自:http://tech.cncms.com/ruanjian/office/excel/95440.html 也许大家可能还不知道Excel中的动态公式是什么,所谓的动态公式,不是普通的公式 ...
- Luke 6:43-45
For no good tree bears bad fruit, nor again does a bad tree bear good fruit, for each tree is known ...
- NOIP2008提高组(前三题) -SilverN
此处为前三题,第四题将单独发布 火柴棒等式 题目描述 给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A.B.C是用火柴棍拼出的整数(若该数非零,则最高位不能是0).用火柴棍拼数字0 ...
- (转)对各种初始化函数的理解:OnInitDialog、InitInstance、InitApplication函数的理解
InitInstance和InitApplication 是 APP 类的初始化.而 OnInitDialog 是在 Dialog 类初始化时调用的函数. ★ 应用程序相关配置,一般在InitInst ...
- Android代码优化----PullToRefresh+universal-image-loader实现从网络获取数据并刷新
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- JMeter学习(十八)JMeter测试Java(二)
实例: 服务为:将输入的两个参数通过IO存入文件: 1.打开MyEclipse,编写Java代码 服务: package test; import java.io.File; import java. ...