一般执行一个操作的过程, 创建对象, 并调用对象的函数, 函数执行, 返回

比如下面的类图, client直接调用Receiver.action

而命令模式, 抽象出command对象, 并在command对象封装对Receiver.action的调用

而client只负责创建command对象(invocation), 并提交给Invoker(通过setCommand), 而command真正的执行(execution)由Invoker控制

从而实现invocation和invoker的分离和解耦合

当然会问, 直接调用那么简单, 为什么要绕那么大的圈来用command?

a. 简化调用过程, 整个调用过程比较繁杂或调用前后需要进行某些额外处理,比如日志,缓存,记录历史操作等

b. 作为"CallBack"在面向对象系统中的替代

c. 支持undo, redo

d. 更关键的是, 命令模式往往会用于异步或并发处理模式

   比如, producer和consumer模式, producer可以不断产生command放到queue里面, 然后可以通过consumer来异步的执行, 达到并发和异步

 

 

命令模式 (Command), 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
这个模式的基本思路是解耦合和责任单一, “行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的, 所以要使用命令模式来解耦合.

场景, 这个模式在平时用的很多, 编辑器里面很常用的'undo/redo', 就是用的这种模式.
经常举的例子就是点菜, 客人可以直接对厨师进行点菜, 这样做有两点不好
1. 客户和厨师紧耦合, 比如厨师换了, 或菜名换了等等, 客户代码需要跟着改变.
2. 厨师除了要烹饪外, 还需要记录每个客户请求, 当客户比较多时, 且客户请求是会变化的, 换个菜, 退个菜, 这个厨师就忙不过来了, 很容易记错. 这就违反了单一责任原则, 厨师就应该负责烹饪, 其他的事应该有专门的waiter负责.
这就是命令模式, 当你需要对请求者的请求(函数调用)进行记录, undo, redo等操作时, 需要单独抽象出Invoker类来处理, 而不要直接耦合在Receiver中.
上面的例子中, 客户是Client, 服务生是Invoker, 厨师是Receiver, 客户请求是Command

class Receiver //最终命令的执行者, 厨师
{
public void Action()
{
//具体的命令执行, 烹饪菜肴
}
} class ConcreteCommand : Command //具体的客户请求, 点一道菜
{
protected Receiver rec; //该情况的执行者, 这道菜哪个厨师烧
public Command(Receiver rec)
{
this.rec = rec;
} public void Execute()
{
rec.Action()//让执行者执行命令
}
} class Invoker //Command模式的核心, 客户请求的管理者, 服务生waiter
{
private List<Command> cmds = new List<Command>(); //用于保存客户请求 public void SetOrder(Command cmd)
{
if Valid(cmd) //需要判断请求是否合理, 比如是否有这道菜
{
cmds.Add(cmd); //增加请求
}
} public void CancelOrder(Command cmd)
{
cmds.Remove(cmd); //删除请求
} public void Execute() //执行所有请求
{
for cmd in cmds
{
cmd.Excute();
}
}
}
public class Client {
public void client(){
//创建接收者
Receiver receiver = new Receiver();
//创建命令对象,设定它的接收者
Command command = new ConcreteCommand(receiver);
//创建Invoker,把命令对象设置进去
Invoker invoker = new Invoker();
invoker.SetOrder(command);
}
}

Invoker具体的实现可能变化多端, 但是本质就是通过Invoke来把客户请求抽象成command, 并且保存和管理commands, 向用户提供如do, redo, undo, rollback等操作, 而这些操作对receiver都是透明的, 这取决于客户和receiver的解耦. 

Design Pattern - 命令模式的更多相关文章

  1. Thinking In Design Pattern——MVP模式演绎

    原文<Thinking In Design Pattern——MVP模式演绎>不知为何丢失了,故重新整理了一遍. 目录 What Is MVP Domain Model StubRepos ...

  2. [Design Pattern] Command Pattern 命令模式

    发现公司的代码好像有用到 Command Pattern,回顾重温下. Command Pattern 的类图结构如下: 参考 <Head First Design Patterns(英文版)& ...

  3. Command Pattern 命令模式

    定义: 命令模式将‘请求’封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象,命令模式也支持可撤销的操作. 类图 如上图所示:Command类是用来声明执行操作的接口:ConcreteCom ...

  4. Command Pattern -- 命令模式原理及实现(C++)

    主要参考<大话设计模式>和<设计模式:可复用面向对象软件的基础>两本书.本文介绍命令模式的实现. What it is:Encapsulate a request as an ...

  5. (Command Pattern)命令模式

    定义 将“请求”封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 结构图: 命令模式的角色划分: Reciever(命令的接收者):接收命令,并知道如何进行必 ...

  6. Design Pattern - 访问者模式

    访问者模式 访问者模式(Visitor), 表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 这个模式相对比较复杂, 而又很少能被用上, 拿G ...

  7. 使用PHP实现命令模式(转)

    <?php /** * 命令模式 2010-08-21 sz * @author phppan.p#gmail.com http://www.phppan.com * 哥学社成员(http:// ...

  8. Command and Query Responsibility Segregation (CQRS) Pattern 命令和查询职责分离(CQRS)模式

    Segregate operations that read data from operations that update data by using separate interfaces. T ...

  9. 深入浅出设计模式——命令模式(Command Pattern)

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

随机推荐

  1. Android实现微信自己主动抢红包的程序

    简单实现了微信自己主动抢红包的服务,原理就是依据keyword找到对应的View, 然后自己主动点击.主要是用到AccessibilityService这个辅助服务,基本能够满足自己主动抢红包的功能, ...

  2. day5:协成函数与import、for...import...的使用

    一.协程函数 1.把函数的执行结果封装好__iter__和__next__,即得到一个迭代器2.与return功能类似,都可以返回值,但不同的是,return只能返回一次值,而yield可以返回多次值 ...

  3. JS高程3:JSON

    JSON,JavaScript Object Notation,JS对象表示法,是目前最常见的传输结构化数据的数据结构. JSON并非编程语言,而是一种数据结构,像mp4.avi一样,只是一种数据格式 ...

  4. [转载]ecmall语言包程序

    [转载]ecmall语言包程序 (-- ::) 转载▼ 标签: 转载 收藏了 原文地址:ecmall语言包程序作者:我思故我在 执行顺序 登陆后台后 最先执行的文件是 default.app.php ...

  5. PHP学习笔记(9)文件上传

    index.php <!doctype html> <html lang="en"> <head> <meta charset=" ...

  6. linux学习笔记14--命令which和whereis

    我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索:        which  查看可执行文件的位置.       whereis 查看文件的位置.         ...

  7. 1. DataBinding - offical tutorial

    1. DataBinding - offical tutorial android DataBinding tutorial 构建环境 数据与布局文件的绑定 data binding 表达式 数据对象 ...

  8. 简单的异步Socket实现——SimpleSocket_V1.1

    简单的异步Socket实现——SimpleSocket_V1.1 笔者在前段时间的博客中分享了一段简单的异步.net的Socket实现.由于是笔者自己测试使用的.写的很粗糙.很简陋.于是花了点时间自己 ...

  9. 今天升级netbean出错

    出现:无法初始化 UI netbean 由于ubuntun装的是open jdk 直接删除open jdk就可以 sudo apt-get autoremove open-jdk*

  10. js 控制按钮点击后不可用

    <input type="button" id="btn" value="免费获取验证码" /> <script type ...