Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Head First 设计模式之命令模式,各司其职提高效率

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

作者头像
用户4361942
发布于 2019-05-24 09:03:10
发布于 2019-05-24 09:03:10
47700
代码可运行
举报
文章被收录于专栏:java程序员思维java程序员思维
运行总次数:0
代码可运行

命令模式

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

命令模式解决的问题

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

命令模式模式角色

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

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

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

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

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

使用场景

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

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

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

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

代码实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 命令(Command)角色
 */
public interface Command {
 public void execute();
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 具体命令
 */
public class LightOffCommand implements Command{
 private Receiver receiver;
 public LightOffCommand(Receiver receiver) {
 this.receiver = receiver;
 }
 public void execute() {
 receiver.turnOFF();
 }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 *
 * 具体命令
 */
public class LightOnCommand implements Command{
 private Receiver receiver;
 public LightOnCommand(Receiver receiver) {
 this.receiver = receiver;
 }
 public void execute() {
 receiver.turnON();
 }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 *
 * 命令接收者:执行命令
 */
public class Receiver {
 public void turnON() {
 System.out.println("执行开灯操作...");
 }
 public void turnOFF() {
 System.out.println("执行关灯操作...");
 }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Created by zengjianlu on 2018/2/24.
 *
 * 命令调用者:负责调用
 */
public class Invoker {
 public void execute(Command command){
 command.execute();
 }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 测试类
 */
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中的命令模式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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方法就是其执行方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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(),调用系统方法,开启一个线程。而接收者是对程序员开放的,可以自己定义接收者。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * jdk Runnable 命令模式
 *
 */
public class TurnOffThread implements Runnable{
 private Receiver receiver;
 public TurnOffThread(Receiver receiver) {
 this.receiver = receiver;
 }
 public void run() {
 receiver.turnOFF();
 }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 测试类
 */
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 设计模式之策略模式,来源于生活,用之于生活

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java程序员思维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
设计模式----命令模式
命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象
大忽悠爱学习
2021/11/15
4100
设计模式(十五):行为型之命令模式
冬天vs不冷
2025/01/21
920
设计模式(十五):行为型之命令模式
设计模式之命令模式
将**请求(一个动作)**封装成对象(命令对象),使得可以用不同的请求对客户进行参数化。
九转成圣
2024/04/10
1310
设计模式之命令模式
「设计模式 JavaScript 描述」命令模式
假设有一个快餐店,而我是该餐厅的点餐服务员,那么我一天的工作应该是这样的:当某位客人点餐或者打来订餐电话后,我会把他的需求都写在清单上,然后交给厨房,客人不用关心是哪些厨师帮他炒菜。我们餐厅还可以满足客人需要的定时服务,比如客人可能当前正在回家的路上,要求 1 个小时后才开始炒他的菜,只要订单还在,厨师就不会忘记。客人也可以很方便地打电话来撤销订单。另外如果有太多的客人点餐,厨房可以按照订单的顺序排队炒菜。
用户8921923
2022/10/24
3810
图解Java设计模式之命令模式
对原理类图的说明 : 1)Invoker 是调用者角色 2)Command :是命令角色,需要执行的所有命令都在这里,可以是或抽象类 3)Receiver :接受者角色,知道如何实施和执行一个请求相关的操作 4)ConcreteCommand :将一个接受者对象与一个动作绑定,调用接受者相应的操作,实现execute
海仔
2020/04/01
4680
图解Java设计模式之命令模式
Java设计模式之命令模式
智能生活项目需求:我们买了一套智能家电,与照明灯、风扇、冰箱、洗衣机,我们只要在手机上安装一个app就可以控制这些家电工作。
shaoshaossm
2022/12/27
3840
Java设计模式之命令模式
命令模式
如上述代码所示,我一共写了两种的电器,一种是点灯,一种是电视,小伙伴们在测试的时候完全可以先写一种,然后再去写第二种,体验一下命令模式的可扩展性,并且它是遵循OCP原则的。
@派大星
2023/06/28
1510
命令模式
命令模式解读
1) 我们买了一套智能家电,有照明灯、风扇、冰箱、洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作。 2) 这些智能家电来自不同的厂家,我们不想针对每一种家电都安装一个 App,分别控制,我们希望只要一个 app就可以控制全部智能家电。 3) 要实现一个 app 控制所有智能家电的需要,则每个智能家电厂家都要提供一个统一的接口给 app 调用,这时 就可以考虑使用命令模式。 4) 命令模式可将“动作的请求者”从“动作的执行者”对象中解耦出来. 5) 在我们的例子中,动作的请求者是手机 app,动作的执行者是每个厂商的一个家电产品
一个风轻云淡
2023/10/15
1450
命令模式解读
命令模式浅析
说起命令模式,第一个引入脑海的是Java的GUI图形化编程,其中就采用了命令模式处理事件。在这个事件处理模型里面,命令对象实现AWT的Listener接口,相当于命令接口。为把一个命令对象与一个AWT的构件连接起来,需要把它登记成一个事件的Listener。构件只认识Listener接口,而不在乎接口是怎么实现的。我们编写一个俄罗斯方块游戏,菜单栏等的事件如下:
孟君
2020/06/19
4250
命令模式.
Topic:我们要制作一个简易的遥控器,有两个控制灯开关的按钮,并有一个操作回退按钮。
JMCui
2018/12/19
2880
设计模式-命令模式
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成一个对象,从而允许使用不同的请求、队列或者日志来参数化其他对象。命令模式支持撤销操作,它的核心思想就是将一个请求封装为一个对象,然后通过不同的命令对象来执行请求。
堕落飞鸟
2023/05/04
2560
06-02-设计模式 命令模式
智能生活项目需求 我们买了一套智能家电,有照明灯、风扇、冰箱、洗衣机,我们只要在手机上安装app就可以控制对这些家电工作。 这些智能家电来自不同的厂家,我们不想针对每一种家电都安装一个App,分别控制,我们希望只要一个app就可以控制全部智能家电。 要实现一个app控制所有智能家电的需要,则每个智能家电厂家都要提供一个统一的接口给app调用,这时就可以考虑使用命令模式。 命令模式可将“动作的请求者”从“动作的执行者”对象中解耦出来. 在我们的例子中,动作的请求者是手机app,动作的执行者是每个厂商的一
彼岸舞
2022/05/28
1890
06-02-设计模式 命令模式
JAVA设计模式15:命令模式,将请求封装为对象,达到读写分离的效果
命令模式是一种行为型设计模式,它将请求封装为对象,使得发送请求的对象和接收请求的对象分离开来。在命令模式中,将一个请求封装成一个对象,这个对象包含了请求的具体信息和执行该请求所需要的方法。通过将请求封装成对象,可以将请求的发送者和接收者解耦,从而使得请求的发送者不需要知道请求是如何被处理的。
Designer 小郑
2023/10/26
4210
JAVA设计模式15:命令模式,将请求封装为对象,达到读写分离的效果
Python 设计模式-命令模式
观察厂商提供的类,你会发现,好多类提供了 on()、off() 方法,除此之外,还有一些方法像 dim()、setTemperature()、setVolumn()、setDirection()。由此我们可以想象,之后还会有更多的厂商类,每个类还会有各式各样的方法。
goodspeed
2020/12/22
4710
Python 设计模式-命令模式
Java设计模式-命令模式
在对象的结构和创建问题都解决了之后,就剩下对象的行为问题了: 如果对象的行为设计的好,那么对象的行为就会更清晰,它们之间的协作效率就会提高. 行为型模式共有11个可供研究,它们分别是:命令模式、解释器模式、访问者模式、模板方法模式、观察者模式、状态模式、策略模式、责任链模式、中介者模式、备忘录模式、迭代器模式. 命令模式 命令模式: 又称动作Action模式, 将请求封装为对象, 从而使我们可用不同的请求对客户进行参数化; 命令可用于将行为请求者与行为实现者解耦, 以适应变化(如: 对请求排队、记录日志、
Java帮帮
2018/03/16
7060
Java设计模式-命令模式
Head First设计模式——命令模式
前言:命令模式我们平常可能会经常使用,如果我们不了解命令模式的结构和定义那么在使用的时候也不会将它对号入座。
SpringSun
2020/08/11
4180
Head First设计模式——命令模式
【一起学系列】之命令模式:封装一个简单Jedis?
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
Kerwin
2020/07/30
3490
【一起学系列】之命令模式:封装一个简单Jedis?
设计模式之命令模式-JS
  假设有一个快餐店,而我是该餐厅的点餐服务员,那么我一天的工作应该是这样的:当某位客人点餐或者打来订餐电话后,我会把他的需求都写在清单上,然后交给厨房,客人不用关心是哪些厨师帮他炒菜。我们餐厅还可以满足客人需要的定时服务,比如客人可能当前正在回家的路上,要求1个小时后才开始炒他的菜,只要订单还在,厨师就不会忘记。客人也可以很方便地打电话来撤销订单。另外如果有太多的客人点餐,厨房可以按照订单的顺序排队炒菜。
青梅煮码
2023/03/13
1.1K0
设计模式-命令模式
命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。
码哥字节
2021/07/27
3690
设计模式--命令模式
命令模式(Command Pattern)是一种行为型设计模式,它将请求封装成对象,以便可以将不同的请求参数化,队列化或记录日志,以及支持可撤销操作。在命令模式中,包含一个命令接口和具体的命令实现类,以及一个调用者(invoker)类和一个接收者(receiver)类。调用者通过调用接口中的方法执行命令,发起请求,接收者则负责实际执行命令。这种设计模式将调用者和接收者解耦,使得系统更加灵活。
软件架构师Michael
2023/07/18
2680
相关推荐
设计模式----命令模式
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验