专栏首页java程序员思维Head First 设计模式之命令模式,各司其职提高效率

Head First 设计模式之命令模式,各司其职提高效率

命令模式

命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。

命令模式解决的问题

命令模式是将行为请求者和行为实现者解耦合的方式。对命令进行封装,将命令和执行命令分隔开。请求的一方发出命令,要求执行某些操作,接受一方收到命令,执行这些操作的真正实现。

命令模式模式角色

客户端(Client)角色:创建一个具体命令(ConcreteCommand)对象并确定其接收者。

命令(Command)角色:声明了一个给所有具体命令类的抽象接口。

具体命令(ConcreteCommand)角色:定义一个接收者和行为之间的弱耦合;实现execute()方法,负责调用接收者的相应操作。execute()方法通常叫做执行方法。

请求者(Invoker)角色:负责调用命令对象执行请求,相关的方法叫做行动方法。

接收者(Receiver)角色:负责具体实施和执行一个请求。任何一个类都可以成为接收者,实施和执行请求的方法叫做行动方法。

使用场景

Transactional behavior(原子事务行为) 借助command模式,可以简单地实现一个具有原子事务的行为。当一个事务失败时,往往需要回退到执 行前的状态,可以借助command对象保存这种状态,简单地处理回退操作。

Thread pools(线程池) 通常一个典型的线程池实现类可能有一个名为addTask()的public方法,用来添加一项工作任务到任务 队列中。该任务队列中的所有任务可以用command对象来封装,通常这些command对象会实现一个通用的接口比如java.lang.Runnable。

命令模式和策略模式的区别

命令模式是含有不同的命令:做不同的事情;隐藏接收者执行细节。策略模式含有不同的算法,做相同的事情;两者关键区别在于是否含有接收者。命令模式含有,策略模式不含有。

代码实现

/**
 * 命令(Command)角色
 */
public interface Command {
 public void execute();
}
/**
 * 具体命令
 */
public class LightOffCommand implements Command{
 private Receiver receiver;
 public LightOffCommand(Receiver receiver) {
 this.receiver = receiver;
 }
 public void execute() {
 receiver.turnOFF();
 }
}
/**
 *
 * 具体命令
 */
public class LightOnCommand implements Command{
 private Receiver receiver;
 public LightOnCommand(Receiver receiver) {
 this.receiver = receiver;
 }
 public void execute() {
 receiver.turnON();
 }
}
/**
 *
 * 命令接收者:执行命令
 */
public class Receiver {
 public void turnON() {
 System.out.println("执行开灯操作...");
 }
 public void turnOFF() {
 System.out.println("执行关灯操作...");
 }
}
/**
 * Created by zengjianlu on 2018/2/24.
 *
 * 命令调用者:负责调用
 */
public class Invoker {
 public void execute(Command command){
 command.execute();
 }
}
/**
 * 测试类
 */
public class Test {
 public static void main(String[] args) {
 Receiver receiver = new Receiver();
 Invoker invoker = new Invoker();
 Command turnOnLight = new LightOnCommand(receiver);
 Command turnOffLight = new LightOffCommand(receiver);
 invoker.execute(turnOnLight);
 invoker.execute(turnOffLight);
 }
}

运行结果:

以上代码存在缺陷,如果增加一个新的命令需要修改Receiver类,违背了开闭原则,可以结合策略模式,将Receiver定义成一个接口,不同的命令使用不同的具体的Receiver,这样就能满足开闭原则。

JDK中的命令模式

public interface Runnable {
 /**
 * When an object implementing interface <code>Runnable</code> is used
 * to create a thread, starting the thread causes the object's
 * <code>run</code> method to be called in that separately executing
 * thread.
 * <p>
 * The general contract of the method <code>run</code> is that it may
 * take any action whatsoever.
 *
 * @see java.lang.Thread#run()
 */
 public abstract void run();
}

Runable是一个典型命令模式,Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法

public synchronized void start() {
 /**
 * This method is not invoked for the main method thread or "system"
 * group threads created/set up by the VM. Any new functionality added
 * to this method in the future may have to also be added to the VM.
 *
 * A zero status value corresponds to state "NEW".
 */
 if (threadStatus != 0)
 throw new IllegalThreadStateException();
 /* Notify the group that this thread is about to be started
 * so that it can be added to the group's list of threads
 * and the group's unstarted count can be decremented. */
 group.add(this);
 boolean started = false;
 try {
 start0();
 started = true;
 } finally {
 try {
 if (!started) {
 group.threadStartFailed(this);
 }
 } catch (Throwable ignore) {
 /* do nothing. If start0 threw a Throwable then
 it will be passed up the call stack */
 }
 }
}

会调用一个native方法start0(),调用系统方法,开启一个线程。而接收者是对程序员开放的,可以自己定义接收者。

/**
 * jdk Runnable 命令模式
 *
 */
public class TurnOffThread implements Runnable{
 private Receiver receiver;
 public TurnOffThread(Receiver receiver) {
 this.receiver = receiver;
 }
 public void run() {
 receiver.turnOFF();
 }
}
/**
 * 测试类
 */
public class TurnOffThreadTest {
 public static void main(String[] args) {
 Receiver receiver = new Receiver();
 TurnOffThread turnOffThread = new TurnOffThread(receiver);
 Thread thread = new Thread(turnOffThread);
 thread.start();
 }
}

优缺点

优点:降低系统的耦合度。新的命令可以很容易地加入到系统中。可以比较容易地设计一个命令队列和宏命令。可以方便地实现对请求的Undo和Redo。

缺点:使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

生活中的命令模式

餐厅点菜场景,客人订单发起者、厨师订单执行者,客人不会直接对厨师直接下单,而是通过服务员这个订单接收者,客人和厨师解耦。如果不这样做会怎样?厨师先去大厅,接受用户的订单,然后厨师拿着订单去做菜,做完菜再把菜端给客人,这个时间段其他用户需要等待,如果采用命令行模式,服务员负责给用户点单,厨师只要负责做好一件事就是做菜,分工明确,客人不需要等待,有点像流水线,提高了用户体验和工作效率。

我的启发

效率是企业的一个重要指标,人效、组织效率、资产效率、战略效率、创新效率,命令模式提供了一种高内聚、低耦合的方式,让不同角色,各司其职,专注自己本职工作,很好的提高用户体验和效率。

设计模式系列历史:

Head First 设计模式之装饰器模式,因为参与,所以认同

Head First 设计模式之单例模式,每个人都是唯一

Head First 设计模式之观察者模式,你我都是发布者和订阅者

Head first 设计模式之策略模式,来源于生活,用之于生活

本文分享自微信公众号 - java程序员思维(java_python_go),作者:曾建路

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • java设计模式之备忘录模式,世上真的有“后悔药”,带你穿越回过去

    备忘录模式(Memento Pattern)模式的定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢...

    用户4361942
  • java设计模式之桥接模式,策略模式旗舰版,世界没有免费的午餐

    桥接(Bridge Pattern)将抽象与实现分离,使它们可以独立变化。它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度,这种类型...

    用户4361942
  • java设计模式之迭代器模式,顾客永远的上帝

    迭代器模式(Iterator Pattern)提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。这种类型的设计模式属于行为型模式。

    用户4361942
  • 设计模式~命令模式

    命令模式允许系统使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

    Vincent-yuan
  • Java 设计模式系列(16) —— 命令模式

    命令模式的定义: 将一个请求封装成为一个对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。

    求和小熊猫
  • JAVA 设计模式 命令模式

    用途 命令模式 (Command) 将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化; 对请求排队或请求日志,以及支持可撤销的操作。 命令模...

    静默虚空
  • 深入Python多进程通信原理与实战——图文

    继上节使用原生多进程并行运行,基于Redis作为消息队列完成了圆周率的计算,本节我们使用原生操作系统消息队列来替换Redis。

    老钱
  • 无人翼交付,颠覆最后一公里

    在Alphabet(没错,就是谷歌的母公司)的子公司Wing Aviation成为第一家获得美国联邦航空管理局航空承运人认证的无人机运输公司后,Wing Avi...

    程序那些事
  • Java之——基于java开发的功能强大、配置灵活的数据库之间的同步工具

    基于java开发的功能强大、配置灵活的数据库之间的同步工具,和数据产生器一样,均是前段时间因为项目需要编写的小工具,在实际应用场景中,我们经常需要定期将一个数据...

    冰河
  • 万物生长,万物互联的时代来了

    一,题记 ? 互联网原住民的四肢已经被技术解放 大脑也已经被科技加持 这个充满奇迹的失控的世界,从此进入了指数增长的人类高能时代 然而我们深知,智能是人类智慧的...

    架构师小秘圈

扫码关注云+社区

领取腾讯云代金券