行为型模式:命令模式

news/2024/7/7 23:19:20

LieBrother原文: 行为型模式:命令模式

十一大行为型模式之三:命令模式。

简介

姓名 :命令模式

英文名 :Command Pattern

价值观 :军令如山

个人介绍

Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations. 将一个请求封装成一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。 (来自《设计模式之禅》)

你要的故事

作为一个程序猿,我们每天都在经历着命令模式,技术经理把需求任务分配给工程师开发,有时因为第三方或者其他不可抗拒的因素导致需求停止开发。这种工作模式就是命令模式。好了,开始故事了。小明在 XX 科技公司做一个安静的程序猿,有一天技术经理给他分配了一个任务:新增黑名单,也就是在他们系统的某个模块里面可以手工对电话打黑名单标签的功能。小明接到任务后就立马开发,在开发了 2 天之后,因为战略原因,技术经理大明暂停了这个开发任务,接下来我们通过非命令模式和命令模式 2 种代码实现来体现这个过程。在这个场景中,为了简单,我们假定技术经理大明手下只有小明一个开发人员。

非命令模式

非命令模式也就是不使用命令模式的代码实现。代码中,我们出现了 Developer 开发人,开发同学是接受技术经理传达的任务,技术经理让他开发哪个需求就开发哪个需求,如果项目有问题需要中断,也需要技术经理评估后传达给开发同学,所以 Developer 有 2 个方法,分别是 develop() 开发需求和 suspend() 暂停需求。 Requirement 则为需求类,TechnicalManager1 则为技术经理类,他有一个方法 action(),通过这个方法来指定开发同学开发任务或者暂停任务。

public class NoCommandTest {public static void main(String[] args) {Developer xiaoMing = new Developer("小明");Requirement requirement = new Requirement("新增黑名单");TechnicalManager1 technicalManager2 = new TechnicalManager1("大明");technicalManager2.setDeveloper(xiaoMing);technicalManager2.action(requirement, "develop");System.out.println("开发了 2 天,需求变故,需要暂停。。。");technicalManager2.action(requirement, "suspend");}}/*** 开发人员*/
class Developer {private String name;public Developer(String name) {this.name = name;}public void develop(Requirement requirement) {System.out.println(this.name + " 开始开发需求:" + requirement.getName());}public void suspend(Requirement requirement) {System.out.println(this.name + " 停止开发需求:" + requirement.getName());}public String getName() {return name;}}/*** 需求*/
class Requirement {private String name;public Requirement(String name) {this.name = name;}public String getName() {return name;}}/*** 技术经理*/
class TechnicalManager1 {private String name;private Developer developer;public TechnicalManager1(String name) {this.name = name;}public void setDeveloper(Developer developer) {this.developer = developer;}public void action(Requirement requirement, String type) {if ("develop".equals(type)) {this.developer.develop(requirement);} else if ("suspend".equals(type)) {this.developer.suspend(requirement);}}}打印结果:
小明 开始开发需求:新增黑名单
开发了 2 天,需求变故,需要暂停。。。
小明 停止开发需求:新增黑名单
复制代码

通过代码,我们可以发现技术经理和开发同学是强依赖关系。如果技术经理下达了一个任务,要求小明写一下周报,这时候得怎么写?是不是小明需要一个写周报的方法,大明也需要新增一个处理事务类型?有没有更好的方法让技术经理不需要做任何改变?命令模式就来解决这个问题。

命令模式

在这个例子中,不管大明叫小明做什么事情,其实都是一样的,就是下达任务命令,让小明去执行命令。我们可以利用命令模式把下达任务这个抽象起来,当做父类,下达开发命令、下达暂停命令、下达写周报等等都是不同的子命令。代码如下。

public class CommandTest {public static void main(String[] args) {Developer xiaoMing = new Developer("小明");Command developCommand = new DevelopCommand(xiaoMing);Command suspendCommand = new SuspendCommand(xiaoMing);Requirement requirement = new Requirement("新增黑名单");TechnicalManager2 technicalManager = new TechnicalManager2("大明");technicalManager.setCommand(developCommand);technicalManager.action(requirement);System.out.println("开发了 2 天,需求变故,需要暂停。。。");technicalManager.setCommand(suspendCommand);technicalManager.action(requirement);}}/*** 命令*/
abstract class Command {protected Developer developer;public Command(Developer developer) {this.developer = developer;}public abstract void execute(Requirement requirement);
}/*** 开始开发*/
class DevelopCommand extends Command {public DevelopCommand(Developer developer) {super(developer);}@Overridepublic void execute(Requirement requirement) {this.developer.develop(requirement);}
}/*** 开发中断*/
class SuspendCommand extends Command {public SuspendCommand(Developer developer) {super(developer);}@Overridepublic void execute(Requirement requirement) {this.developer.suspend(requirement);}
}/*** 技术经理*/
class TechnicalManager2 {private String name;private Command command;public TechnicalManager2(String name) {this.name = name;}public void action(Requirement requirement) {this.command.execute(requirement);}public void setCommand(Command command) {this.command = command;}
}打印结果:
小明 开始开发需求:新增黑名单
开发了 2 天,需求变故,需要暂停。。。
小明 停止开发需求:新增黑名单
复制代码

代码中用 Command 来抽象下达任务,而技术经理 TechnicalManager2 并没有和 Developer 有直接的关系,而是 TechnicalManager2 和 Command 建立的联系,Command 和 Developer 建立了联系。这样子把大明和小明的强依赖关系给剥离开,而新增一个下达写周报的任务也很简单,在 Developer 中新增一个处理写周报的方法,新增一个写周报的 Command 子类,就可以了,TechnicalManager2 如上面所愿不用修改。这就是完整的一个命令模式代码。

代码: Command Pattern

总结

从文章中我们就可以看到,利用命令模式能够进行类的解耦,让调用者和接受者没有任何关系,也通过对行为的抽象,让新增其他行为变得清晰容易,也就是可扩展性大大增加

参考资料:《大话设计模式》、《设计模式之禅》

推荐阅读:

公众号之设计模式系列文章

希望文章对您有所帮助,设计模式系列会持续更新,感兴趣的同学可以关注公众号:LieBrother,第一时间获取文章推送阅读,也可以一起交流,交个朋友。


http://lihuaxi.xjx100.cn/news/236153.html

相关文章

Win7编译volley成jar包

首先安装git和ant,当然jdk也是必须的。 git clone搞到volley的源码。 git clone https://android.googlesource.com/platform/frameworks/volley 此时volley的目录里面应该是这样的,没有AndroidManifest.xml文件。 cd进volley目录,敲下一…

springMVC自定义全局异常

SpringMVC通过HandlerExceptionResolver处理程序异常&#xff0c;包括Handler映射&#xff0c;数据绑定以及目标方法执行时所发生的异常。 SpringMVC中默认是没有加装载HandlerExceptionResolver&#xff0c;我们需要在SpringMVC.xml中配置 <mvc:annotation-driven /> 1、…

Python之机器学习K-means算法实现

一、前言&#xff1a; 今天在宿舍弄了一个下午的代码&#xff0c;总算还好&#xff0c;把这个东西算是熟悉了&#xff0c;还不算是力竭&#xff0c;只算是知道了怎么回事。今天就给大家分享一下我的代码。代码可以运行&#xff0c;运行的Python环境是Python3.6以上的版本&#…

Win7下用VS2010编译QGIS2.9.0

折腾了两天了&#xff0c;终于吧QGIS2.9.0在VS2010下面编译过了。 参考了许多的博客&#xff0c;在网络环境极为和&#xff08;e&#xff09;谐&#xff08;lie&#xff09;的情况下用Google查了好多资料。 其实原创的东西真的不多&#xff0c;但是毕竟是自己亲身实践得到的成…

iOS 绘制圆角

级别&#xff1a; ★☆☆☆☆ 标签&#xff1a;「iOS切圆角」「layer圆角」「CAShapeLayer圆角」 作者&#xff1a; XsH 审校&#xff1a; QiShare团队 项目中会常有圆角&#xff08;或圆形&#xff09;显示视图的需求&#xff08;比如用户头像的显示&#xff09;&#xff0c;也…

php面试问答

结合实际PHP面试&#xff0c;汇总自己遇到的问题&#xff0c;以及网上其他人遇到的问题&#xff0c;尝试提供简洁准确的答案包含MySQL、Redis、Web、安全、网络协议、PHP、服务器、业务设计、线上故障、个人简历、自我介绍、离职原因、职业规划、准备问题等部分 GitHub: https:…

WinXp安装Oracle 11g Express Edition

由于在虚拟机上学习&#xff08;怕把真机器搞坏了&#xff09;&#xff0c;这次是在Windows XP上安装Oracle 11g Express。 本文安装的是Oracle 11g Express&#xff0c;是Oracle数据库的快速版&#xff08;学习版&#xff09;&#xff0c;安装包大小只有几百MB。 到Oracle的…

SnackbarUtilDemo【Snackbar的封装类】

版权声明&#xff1a;本文为HaiyuKing原创文章&#xff0c;转载请注明出处&#xff01; 前言 这个工具类参考的是《没时间解释了&#xff0c;快使用Snackbar!——Android Snackbar花式使用指南》&#xff0c;代码几乎一样&#xff0c;所以想要了解具体原理或者更详细信息请阅读…