最近想开始多学习一下工作中代码常常使用的设计模式。

除单例模式,工厂模式之外,command模式用的也是比较多的。

在学习了“正统”的设计模式之后,再来看实际项目代码中使用的类似的设计模式,发现还是有差别的——事实上,设计模式更多的是一种思想吧,如果凡事都寻求一个固定的模式,很容易陷入过度设计的误区。

设计模式是前人在开发过程中总结出来的经验,而并非一套标准,实际使用中,需要结合具体的业务来进行设计,而不应该拘泥于固定的模式。

Command模式

基本动机:解耦程序动作的发起与实际执行

简单的例子:
战场上班长(Invoker,调用者)下达命令(Command):机枪掩护(具体的Comnand对象1),步兵冲锋(具体的Command对象2),但实际机枪怎么打,每个步兵(Receiver)怎么冲则属于执行的事,并非都由班长计划好的。不同的兵将会有不同的冲锋路径。Command模式的解耦机制一可实现多态,二可实现异步(动作发起并不意味着马上执行)。

再次梳理一下:
班长(Invoker)下达命令(Command)并指定命令的接收者(Receiver,也是命令的执行者)。之后班长喊“冲”(action),对应的Receiver便开始执行任务。

类图:

时序图:

代码示例:

命令接收者相关类:

// 接收者01,实现自己的业务逻辑
class Receiver01 {  public void doJob() {  System.out.println("接收者01 完成工作 ...\n");  }
}  // 接收者02,实现自己的业务逻辑
class Receiver02 {  public void doJob() {  System.out.println("接收者02 完成工作 ...\n");  }
} 

命令类:

// 抽象命令类,定义了每个具体命令被执行的入口方法execute()
abstract class AbstractCommand {  public abstract void execute();
}  // 具体命令类01,通过构造函数的参数决定了该命令由哪个接收者执行
class Command01 extends AbstsractCommand {  private AbstractReceiver receiver = null;  public Command01(AbstractReceiver receiver) {  this.receiver = receiver;  }  public void execute() {  System.out.println("命令01 被发布 ...");  this.receiver.doJob();  }
}  // 具体命令类02,通过构造函数的参数决定了该命令由哪个接收者执行
class Command02 extends AbstractCommand {  private AbstractReceiver receiver = null;  public Command02(AbstractReceiver receiver) {  this.receiver = receiver;  }  public void execute() {  System.out.println("命令02 被发布 ...");  this.receiver.doJob();  }
} 

调用者类:

// 调用者,负责将具体的命令传送给具体的接收者
class Invoker {  private AbstractCommand command = null;  public void setCommand(AbstractCommand command) {  this.command = command;  }  public void action() {  this.command.execute();  }
} 

测试类:

//测试类
public class Client {  public static void main(String[] args) {  // 创建调用者  Invoker invoker = new Invoker();  // 创建一个具体命令,并指定接收并执行该命令的具体接收者  AbstractCommand command01 = new Command01(new Receiver01());  // 给调用者发布一个具体命令invoker.setCommand(command01);  // 调用者执行命令,其实是将其传送给具体的接收者并让其真正执行  invoker.action();AbstractCommand command02 = new Command01(new Receiver02());  invoker.setCommand(command02);  invoker.action();  }
} 

测试结果:
命令01 被发布 …
接收者01 完成工作 …

命令02 被发布 …
接收者02 完成工作 …

特点

Command的模式最大的一个特点就是调用者与接收者的解耦。

实际应用中,Command的Receiver是多种多样的。比如文本编辑器,CopyCommand对应的是Edit控件的Copy接口,ExitCommand可能对应的就是Application的Exit接口,等等。通过Command模式,就可以实现调用的一致性,而Receiver可能还是千差万别的,因此需要在客户端 Client 类中显式指明出来。

项目中的command模式

前面说了,设计模式是从项目中抽象出来的,服务于项目。实际上我工作中遇到的command模式与上面讲的不太一样,大致如下:

一个command基类;

具体的command继承自command基类,对外只暴露execute接口。

业务线程持有多个具体command对象的指针,并在初始化线程的时候通过new操作获得实例化的command对象。

之后业务对外的接口中调用相应command的execute函数来处理具体的业务逻辑。

也就是说,这里并没有receiver这个角色,具体的执行任务由command来承担——这是基于业务本身的特点的。

另外,也没有使用Invoker——业务线程本身就是调用者了,没必要再多此一举进行这一层封装。

总之,先把死的模式学了,再在实际应用中用活起来!

【设计模式】Command模式相关推荐

  1. 解读设计模式----命令模式(Command Pattern)

    ***本文与作者原文有一定的偏差,其中加入了一部分是个人看法,详细请查看作者原文.*** 原文连接http://www.dofactory.com/Patterns/PatternCommand.as ...

  2. 设计模式学习笔记——命令(Command)模式

    设计模式学习笔记--命令(Command)模式 @(设计模式)[设计模式, 命令模式, command] 设计模式学习笔记命令Command模式 基本介绍 命令案例 类图 实现代码 Command接口 ...

  3. C++设计模式——命令模式(command pattern)

    一.原理讲解 别名动作(action),事务(transaction). 1.1意图 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 ...

  4. 设计模式--命令(Command)模式

    模式定义 将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 类图 要点总结 Command模式的根本目的在于将"行为请 ...

  5. C++设计模式-Command命令模式

    Command命令模式 作用:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 由于"行为请求者"与"行 ...

  6. 设计模式简单代码之Command模式(皇帝圣旨篇)

    作者:一雨田( http://blog.csdn.net/dylgsy/ ).本文欢迎转贴,并请保留此信息 在现实的情况中,有一个实例能非常贴切的描述了Command模式,这就是皇帝和士兵的关系.皇帝 ...

  7. Python设计模式-命令模式

    Python设计模式-命令模式 代码基于3.5.2,代码如下; #coding:utf-8 #命令模式class barbecuer():def bakeButton(self):print(&quo ...

  8. [Head First设计模式]餐馆中的设计模式——命令模式

    系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...

  9. 使用Command模式实现撤销机制 (Code Project 精选翻译)

    使用Command模式实现撤销机制[1] Written by Matt Berther Translated by Allen Lee[2] Reviewed by Teddy Tam & ...

最新文章

  1. 《编写可维护的JavaScript》——1.7 直接量
  2. R语言使用caret包中的createFolds函数对机器学习数据集进行交叉验证抽样、返回的样本列表长度为k个
  3. 项目福利政策报名 | 项目启动资金、股权投资、住房购房补贴
  4. Swift翻译之-Swift语法入门 Swift语法介绍
  5. ggplot2 | 如何对连续型变量使用离散型调色板进行配色
  6. 信息系统项目管理系列之六:项目范围管理
  7. C++11 非成员函数begin()、end()
  8. Tomcat8安装(或卸载重装)
  9. 通达信标记符号_史上最全的通达信软件中常见的一些字母/字符标识的含义(图解)...
  10. 用VScode写C/C++,从下载安装到配置使用
  11. 你真的懂智慧园区数字平台?快来看看吧
  12. python使用while实现无限循环_python 基础之while无限循环
  13. sdcc 51 迁移记录
  14. 振作起来,开始认真搞了
  15. 本地颁发 SSL 证书,并开启 https 服务调试
  16. Redis 9种数据结构
  17. jQuery File Upload
  18. 白痴学日语系列之初识日语(七)附语法二
  19. html登录错误有提示,为什么我登录之后的提示老是网页上有错误呢?
  20. expire_logs_days

热门文章

  1. ipconfig命令
  2. Nginx配置与踩坑
  3. 金蝶系统未连接sql服务器,sql 怎么与金蝶连接服务器配置
  4. Google排名内部优化攻略
  5. .NET程序设计 实验名称 实验六 ASP.NET服务器控件
  6. 个人博客网建站优化经验总结(上)
  7. code-server安装 ipadPro网页编程
  8. linux mint 中文官网,Linux Mint OS 19中文纯净版(薄荷定制)
  9. 春运首日火车票开始网上订票和电话订票
  10. 红松获亿元融资,中老年在线兴趣社区会是一门“朝阳”生意么?