【设计模式】Command模式
最近想开始多学习一下工作中代码常常使用的设计模式。
除单例模式,工厂模式之外,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模式相关推荐
- 解读设计模式----命令模式(Command Pattern)
***本文与作者原文有一定的偏差,其中加入了一部分是个人看法,详细请查看作者原文.*** 原文连接http://www.dofactory.com/Patterns/PatternCommand.as ...
- 设计模式学习笔记——命令(Command)模式
设计模式学习笔记--命令(Command)模式 @(设计模式)[设计模式, 命令模式, command] 设计模式学习笔记命令Command模式 基本介绍 命令案例 类图 实现代码 Command接口 ...
- C++设计模式——命令模式(command pattern)
一.原理讲解 别名动作(action),事务(transaction). 1.1意图 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 ...
- 设计模式--命令(Command)模式
模式定义 将一个请求(行为)封装为一个对象,从而使你可用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作 类图 要点总结 Command模式的根本目的在于将"行为请 ...
- C++设计模式-Command命令模式
Command命令模式 作用:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤销的操作. 由于"行为请求者"与"行 ...
- 设计模式简单代码之Command模式(皇帝圣旨篇)
作者:一雨田( http://blog.csdn.net/dylgsy/ ).本文欢迎转贴,并请保留此信息 在现实的情况中,有一个实例能非常贴切的描述了Command模式,这就是皇帝和士兵的关系.皇帝 ...
- Python设计模式-命令模式
Python设计模式-命令模式 代码基于3.5.2,代码如下; #coding:utf-8 #命令模式class barbecuer():def bakeButton(self):print(&quo ...
- [Head First设计模式]餐馆中的设计模式——命令模式
系列文章 [Head First设计模式]山西面馆中的设计模式--装饰者模式 [Head First设计模式]山西面馆中的设计模式--观察者模式 [Head First设计模式]山西面馆中的设计模式- ...
- 使用Command模式实现撤销机制 (Code Project 精选翻译)
使用Command模式实现撤销机制[1] Written by Matt Berther Translated by Allen Lee[2] Reviewed by Teddy Tam & ...
最新文章
- 《编写可维护的JavaScript》——1.7 直接量
- R语言使用caret包中的createFolds函数对机器学习数据集进行交叉验证抽样、返回的样本列表长度为k个
- 项目福利政策报名 | 项目启动资金、股权投资、住房购房补贴
- Swift翻译之-Swift语法入门 Swift语法介绍
- ggplot2 | 如何对连续型变量使用离散型调色板进行配色
- 信息系统项目管理系列之六:项目范围管理
- C++11 非成员函数begin()、end()
- Tomcat8安装(或卸载重装)
- 通达信标记符号_史上最全的通达信软件中常见的一些字母/字符标识的含义(图解)...
- 用VScode写C/C++,从下载安装到配置使用
- 你真的懂智慧园区数字平台?快来看看吧
- python使用while实现无限循环_python 基础之while无限循环
- sdcc 51 迁移记录
- 振作起来,开始认真搞了
- 本地颁发 SSL 证书,并开启 https 服务调试
- Redis 9种数据结构
- jQuery File Upload
- 白痴学日语系列之初识日语(七)附语法二
- html登录错误有提示,为什么我登录之后的提示老是网页上有错误呢?
- expire_logs_days