命令模式是我们能够实现发送者和接收者之间的完全解耦,发送者是调用操作的对象,而接收者是接收请求并执行特定操作的对象。通过解耦,发送者无需了解接收者的接口。在这里,请求的含义是需要被执行的命令。

作用

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。当将客户的单个请求封装成对象以后,我们就可以对这个请求存储更多的信息,使请求拥有更多的能力;命令模式能够把请求发送者和接收者解耦,使得命令发送者不用去关心请求将以何种方式被处理。

类视图

实现

class Command;
/*调用者(Invoker)*/
class Switch
{
public:
Switch(){}
~Switch(){}
void insertcommand(Command* pCom)
{
m_command.pus_back(pCom);
}
void excuteonce()
{
if (m_command.empty())
return;
m_command.front()->excute();
m_command.pop_front();
}
private:
list< share_prt<Command*> > m_command;
};
/*接收者(Recever)*/
class Appliance
{
public:
Appliance(){}
virtual ~Appliance(){}
virtual bool start() = 0;
virtual bool stop() = 0;
}; class AirConditioner : public Appliance
{
public:
AirConditioner(){}
virtual ~AirConditioner(){}
bool start()
{
cout <<"the air conditioner is on" << endl;
}
bool stop()
{
cout <<"the air conditioner is off" << endl;
}
}; class Fridge : public Appliance
public:
Fridge(){}
virtual ~Fridge(){}
bool On()
{
cout <<"the firdge is on" << endl;
}
bool Off()
{
cout <<"the firdge is off" << endl;
}
};
/*命令(Command)*/
class Command
{
public:
Command(Appliance* pAl): m_pAlice(pAl){}
virtual ~Command(){}
virtual excute();
protected:
Appliance* m_pAlice;
}; class OnCommand : public Command
{
public:
OnCommand(Appliance* pAl): Command(pAl){}
virtual ~OnCommand(){}
bool excute()
{
m_pAlice.On();
}
}; class OffCommand : public Command
{
public:
OffCommand(Appliance* pAl): Command(pAl){}
virtual ~OffCommand(){}
bool excute()
{
m_pAlice.Off();
}
}; int main()
{
//接收者
AirConditioner air;
Fridge fridge;
//生成命令
OnCommand On1(&air);
OnCommand On2(&fridge);
OffCommand off1(&air);
OffCommand off2(&fridge);
//发送命令
Switch switcher;
switcher.insertcommand(&on1);
switcher.insertcommand(&on2);
switcher.insertcommand(&off1);
switcher.insertcommand(&off2);
//执行命令
switcher.excuteonce();
switcher.excuteonce();
switcher.excuteonce();
switcher.excuteonce(); }

从如上的例子中可以分析出,调用者switch不会关心是开命令还是关命令,是属于空调的命令还是冰箱的命令,这样一方面可以做到解耦的效果,另一方面,还可以对接收者和命令进行方便的扩展,这就是命令模式的核心优点所在。当然缺点也正是如此,接收者和命令的组合数量是MxN的关系,再扩展是需要注意数量级的大小。

应用场景

  1. 通过参数化对象实现功能执行,命令是面向对象式的,而不是回调函数式的;
  2. 指定消息队列并在不同时间执行请求。一个命令对象可以有独立于原始请求的生命周期。如果一个请求的接收者可以由一个独立地址空间的方式来表示,那么你可以将请求对象的命令转换到不同的进程空间并在其中完成请求。
  3. 支持撤销。命令的执行操作可以作为状态进行存储,并在需要时实现命令撤销,命令的接口必须增加一个unexcude操作,进行撤销操作的执行。
  4. 支持日志记录变化,在系统崩溃的情况下使用命令可以重新应用。通过增加load和store操作命令接口,可以保存一个持续变化的日志,从系统崩溃中恢复,需要重新加载日志命令和使用excute操作重新执行这些命令。
  5. 通过在原生操作基础上的高层操作构建系统。这样的结构在支持交易操作的系统中很常见。一个交易事物封装一组变化的数据,命令模式提供了一种交易模型,命令都有一个共同的接口,允许你使用相同的方式调用所有的交易。这种模式也使得它很容易与新的交易系统进行交互扩展。

设计模式之命令模式(Command )的更多相关文章

  1. 设计模式 ( 十三 ) 命令模式Command(对象行为型)

    设计模式 ( 十三 ) 命令模式Command(对象行为型) 1.概述         在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需 ...

  2. 乐在其中设计模式(C#) - 命令模式(Command Pattern)

    原文:乐在其中设计模式(C#) - 命令模式(Command Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 命令模式(Command Pattern) 作者:webabcd ...

  3. 面向对象设计模式_命令模式(Command)解读

    在.Net框架中很多对象的方法中都会有Invoke方法,这种方法的设计实际是用了设计模式的命令模式, 模式图如下 其核心思路是将Client 向Receiver发送的命令行为进行抽象(ICommand ...

  4. 二十四种设计模式:命令模式(Command Pattern)

    命令模式(Command Pattern) 介绍将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可取消的操作. 示例有一个Message实体类,某个 ...

  5. 设计模式-15命令模式(Command Pattern)

    1.模式动机 在软件设计中,我们经常需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是哪个,我们只需在程序运行时指定具体的请求接收者即可,此时,可以使用命令模式来进行设计,使 ...

  6. [设计模式] 14 命令模式 Command

    Command 模式通过将请求封装到一个对象(Command)中,并将请求的接受者存放到具体的 ConcreteCommand 类中(Receiver)中,从而实现调用操作的对象和操作的具体实现者之间 ...

  7. 设计模式之命令模式(Command)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  8. 大熊君说说JS与设计模式之------命令模式Command

    一,总体概要 1,笔者浅谈 日常生活中,我们在看电视的时候,通过遥控器选择我们喜欢的频道时,此时我们就是客户端的角色,遥控器的按钮相当于客户请求,而具体执行的对象就是命令对象, 命令模式把一个请求或者 ...

  9. 设计模式 笔记 命令模式 Command

    //---------------------------15/04/25---------------------------- //Conmmand  命令模式----对象行为型模式 /* 1:意 ...

  10. 行为型设计模式之命令模式(Command)

    结构 意图 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作. 适用性 抽象出待执行的动作以参数化某对象,你可用过程语言中的回调(c a ...

随机推荐

  1. spark中RDD的transformation&action

    简介: 1,transformation是得到一个新的RDD,方式很多,比如从数据源生成一个新的RDD,从RDD生成一个新的RDD 2,action是得到一个值,或者一个结果(直接将RDDcache到 ...

  2. Android开发的插件Code Generator与LayoutCreator的安装与使用,提升你的开发效率

    前言 大家好,给大家带来Android开发的插件Code Generator与LayoutCreator的安装与使用,提升你的开发效率的概述,希望你们喜欢 学习目标 掌握两个插件的安装和使用,能够实现 ...

  3. 教你怎么看网站是用react搭建的

    概述 SPA和react可以说是web开发的分水岭,我一直在寻找判断网站是普通网站还是SPA抑或是react的方法.今天突然找到一个判断网站是不是react搭建的简便方法.现在记录下来供以后开发时参考 ...

  4. 详解 leetcode 猜数字大小 II

    375. 猜数字大小 II 原题链接375. 猜数字大小 II 题目下方给出了几个提示: 游戏的最佳策略是减少最大损失,这引出了 Minimax 算法,见这里,和这里 使用较小的数开始(例如3),看看 ...

  5. 微信开发-PC调试-JS-SDK功能之分享功能调试

    一般涉及和第三方的开发调试,都会比较麻烦些.不过,像微信这样的大公司呢,产品技术是过硬的,所以,基本上只要自己把文档看仔细了,弄好了,基本就没有问题了. 对于后端接口一类的调试,主要就是通过打印访问日 ...

  6. fiddler 使用方法汇总

    作为网络开发人员,怎能不使用一些抓包工具呢?fiddler是个不错的选择. 不过,一般情况下,我们往往使用浏览器自带的控制台的[网络]选项就可以达到查看数据的通信情况了,当然,一些浏览器不容易捕捉的事 ...

  7. IDEA搭建SSM实现登录、注册,数据增删改查功能

     本博文的源代码:百度云盘/java/java实例/SSM实例/SSM实现登录注册,增删改查/IDEA搭建SSM实现登录,注册,增删改查功能.zip 搭建空的Maven项目 使用Intellij id ...

  8. Testing - 软件测试知识汇总

    软件测试知识梳理 基础概念 : http://www.cnblogs.com/anliven/p/6070000.html 测试分类 : http://www.cnblogs.com/anliven/ ...

  9. Django model update的各种用法介绍

    Django开发过程中对表(model)的增删改查是最常用的功能之一,本文介绍笔者在使用model update过程中遇到的那些事 model update常规用法 假如我们的表结构是这样的 clas ...

  10. Python系列之环境安装

    Python可以实现强大的数据爬虫功能,并且数据分析与挖掘挺方便,也提供了大量的库,比如numpy, pands,matplotlib等.尤其,使用Python做机器学习也成了近年来的趋势,有人经常会 ...