设计模式——命令模式(Command Pattern)

嵌入式开发 DSP芯片运行方式(挖坑-填坑中-坑已平 :)) TMS320F28335 DSP 芯片 如何将运行代码放在不同的位置 阅读详情

一、命令模式的定义

将“请求”封装成对象,以便使用不同的请求,队列或者日志来参数化其他对象。命令模式也支持可撤销。

这里写图片描述

命令接口–ICommand
public interface ICommand {
    public void execute();
    public void undo();
}

定义统一的接口,所有的命令类都需要实现该接口。

命令类–ConcreteCommand
public class ConcreteCommand implements ICommand {
    private Reciever reciever;
    public ConcreteCommand(Reciever receiver) {
        this.reciever = receiver;
    }
    public void execute() {
        reciever.action();
    }

    public void undo() {
        reciever.undo();
    }
}

将某一个具体的“请求”封装成具体的命令类,实现ICommand接口。命令模式的核心目的是将发出请求的对象和执行请求的对象解耦,被解耦的两者之间是通过命令对象进行沟通的,命令对象封装了接受者及其一个或多个动作。比如:开灯命令,可以是LightOnCommand;

命令执行者—Reciever
public class Reciever {
    private String recieverName;
    pubic Reciever(String name) {
        this.recieverName = name;
    }
    public void action() {
        System.out.println("do action...");
    }
    public void undoAction() {
        System.out.println("undo action ...");
    }
}

该类是真正执行命令的类,实质上它根本不知道ICommand和Command的存在,所以它只要纯粹完成自己的逻辑。比如一个电灯类(Light),就只需要实现开关电灯的逻辑,并暴露出调用接口就行了。

调用者–Invoker
public class Invoker {
    private ICommand command;
    public Invoker() {}
    public void setCommand(ICommand command) {
        this.command = command;
    }
    // 调用创建时就设置好的命令对象
    public invokeCommand() {
        this.command.execute();
    }

    // 动态调用通过参数传过来的命令对象
    public invokeCommand(ICommand command) {
        command.execute();
    }
    public invokeUndo() {
        this.command.undo();
    }
}

命令的调用者,它持有一个或者多个命令对象,在某个时间点调用命令对象的execute方法,将请求付诸执行。

客户端–Client
public class Client {
        Receiver reciever = new Reciever();   
        ICommand c = new ConcreteCommand(reciever);    
        Invoker invoker = new Invoker();   
        invoker.setCommand(c);   
        invoker.invokeCommand(); 
}

负责创建具体的命令对象,并设置命令的执行者。

宏命令
public class MacroCommand implements ICommand {
    ICommands[] commands;
    public MacroCommand(ICommand[] commands) {
        this.commands = commands;
    }

    public void execute() {
        for (int i=0; i<commands.length; i++) {
            commands[i].execute();
        }
    }

    public void undo() {
        for (int i=0; i<commands.length; i++) {
            commands[i].undo();
        }
    }
}

宏命令的目的是,制造一种新的命令来执行其他一堆命令。这样这个宏命令也是一个实现了ICommand的命令对象,因此可以普通的命令对象一样被执行。

二、一个具体的例子

实现一个控制电灯开关的遥控器,有三个功能:开、关、撤销操作。

/**
 * 命令真正执行者,对应类图中的Reciever
 */
public class Light {
    public void onLight() {
        System.out.println("light on...");
    }

    public void offLight() {
        System.out.println("light off...");
    }

    public void undo() {
        System.out.println("light undo...")
    }
}

/**
 * 开灯命令,对应类图中的ConcreteCommand
 */
public class LightOnCommand implements ICommand{
    private Light light;
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.onLight();
    }
    public void undo() {
        light.undo();
    }
}
/**
 * 关灯命令,对应类图中的ConcreteCommand
 */
public class LightOffCommand implements ICommand{
    private Light light;
    public LightOffCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.offLight();
    }
    public void undo() {
        light.undo();
    }
}

/**
 * 定义一个空命令对象,它是一个空对象,不做任何事情。可能遥控器在出厂时并没有
 * 设置真正有效的命令对象,就可以用空对象代替,以便后续在设置真正的命令对象。
 */
public class NoCommand implements ICommand {
    public void execute(){}
    public void undo(){}
}

/**
 * 命令调用者,对应类图中的Invoker
 */
public class LightController {
    // 持有多个命令对象
    private ICommand[] commands;
    // 记录前一个命令对象,用于“撤销”操作
    private ICommand undoCommand;

    public LightController() {
        // 用于保存开和关两个命令对象
        this.commands = new ICommand[2];
        // 初始化
        ICommand noCommand = new NoCommand();
        for(int i=0; i<2; i++){
            command[i] = noCommand;
        }
        undoCommand = noCommand;
    }

    public void setCommands(ICommand onCommand, ICommand offCommand) {
        // 第一个元素被设为开命令对象
        commands[0] = onCommand;
        commands[1] = offCommand;
    }
    // 按下打开电灯的按钮(请求打开电灯)
    public void onButtonPushed() {
        commands[0].execute();
        undoCommand = commands[0];
    }
    // 按下打关电灯的按钮(请求关掉电灯)
    public void offButtonPushed() {
        commands[1].execute();
        undoCommand = commands[1];
    }

    // 按下撤销按钮,由对应的命令对象执行其撤销操作
    pubic void undoButtonPushed() {
        undoCommand.undo();
    }
    // ...其他代码
}

/**
 * 创建者,对应类图中的Client类
 */
public class LightControllerTest {
    public void static main(String[] args) {
        // 创建命令对象及其执行者
        Light light = new Light();
        LightOnCommand onCommand = new LightOnCommand(light);
        LightOffCommand offCommand = new LightOffCommand(light);

        LightController lightController = new LightController();
        lightController.setCommands(onCommand, offCommand);

        // 测试
        lightController.onButtonPushed();
        lightController.offButtonPushed();
        lightController.undoButtonPushed();
    }
}

三、优缺点

优点
  • 将发出请求的对象与执行请求的对象解耦。
  • 调用者可以执行通过参数传过来的命令对象,因而可以在运行时动态执行命令。
  • 命令的发送者和命令执行者有不同的生命周期。命令发送了并不是立即执行。
  • 可以使用宏命令任意组合一些命令,比如实现“一键式家居控制”的需求,就可以将各种家电的命令对象组合成一组。
  • 因为将“请求”封装成了对象,使得命令可以被传递,被延时执行。比如,将命令对象发送到远程服务进行执行;也可以将命令对象扔到队列中,由专门的执行命令线程进行执行,执行命令的线程不需要知道具体命令内容,只要是实现了ICommand接口的对象,它都可以执行。
  • 因为将“请求”封装成了对象,从而使得可以对请求的执行过程进行一些控制。比如“撤销”操作可以让命令执行失败之后,进行撤销,可用于事务执行。
  • 可将命令记录到日志,系统故障后恢复等。
缺点
  • 每一个命令都封装为命令对象,导致类太多。
  • 对于这一点,个人感觉不需要如此细的粒度,比如LightOnCommand,LightOffCommand,只要设计一个合适的数据结构,通过数据来表达,就可以省掉很多类,代码的灵活和可扩展性也不受影响。

四、应用场景

队列

命令对象扔到队列中,由专门的执行命令线程进行执行,执行命令的线程不需要知道具体命令内容,只要是实现了ICommand接口的对象,它都可执行。因为命令模式下请求者和执行者可以有不同的生命周期,所以命令对象在创建很久以后,仍然可以被执行。另外,可以使用线程池来执行这些命令,只要这些命令实现Runable接口。

日志

因为命令对象可以对命令自身进行管理,比如可以输出命令日志,所以可以用于“容灾”等需要记录所有命令的应用。在这些应用中,命令对象中新增记录日志将命令存储到磁盘中,一旦系统崩溃或死机,重启后可以重新加载命令,再批次执行命令对象的execute方法。比如数据库事务处理,电子表格等应用。

状态条

如果假如系统需要按顺序执行一系列的命令操作,并且需要了解命令执行进度和状态,则可以让每个命令对象都提供一个获取命令执行状态的方法,系统调用该方法显示状态。

需要多级撤销或重做操作

可以在Invoker中用一个栈来存储执行过的命令对象,一旦需要撤销或重做操作,可以通过pop出最近的一个命令对象,并执行其undo方法。

web服务请求处理

将每个web请求封装成一个命令对象。比如struts框架中,就用到了命令模式: Struts框架中,在模型层都要继承一个Action接口,并实现execute方法,其实这个Action就是命令类。为什么Struts会应用命令模式,是因为Struts的核心控制器ActionServlet只有一个,相当于Invoker,而模型层的类会随着不同的应用有不同的模型类,相当于具体的Command。这样,就需要在ActionServlet和模型层之间解耦,而命令模式正好解决这个问题。

【无人机基站】基于K-mean算法实现无人机基站部署附matlab代码 阅读详情

相关推荐

Telegram AI Bot自动化实战:5步用Make搭建业务工作台

Telegram Bot 是一种轻量级、高抵达率的消息自动化载体,其核心价值在于将结构化消息(如text、photo、callback_query)转化为可编程的事件流。基于 Bot API 的简洁设计与 Webhook 机制,开发者无需复杂鉴权即可实现毫秒级响应。结合低代码平台 Make,可快速构建具备上下文识别、条件路由、多系统分发与错误熔断能力的自动化流程。该方案特别适用于客服分发、数据同步、IoT告警等高频、规则明确、需即时反馈的业务场景,显著降低对 Python/Node.js 编程与 DevOp

weixin_33158887的博客 299

命令(ICommand)基础

命令可以看做事件的进化版,使用命令,可以使代码结构更清晰;还能更好的控制各个UI的状态(启用/禁用)。

FoolRabbit的专栏 9155

基于stm32开发的红外循迹小车

2.L298N电机驱动模块:分别是5V,12V,GND,可以通过外加电源给驱动模块供电,IN1,IN2,IN3,IN4,EN1,EN2,通过给IN口不同的电平,可以达到控制电机正反转,EN口为使能口,可以通过给EN口不同的PWM波,来达到控制小车速度,1.红外循迹模块:检测黑线的原理是向外发射红外线,当没有遇到黑线的时候,返回回来,之后返回高电平,当遇到黑线的时候,红外被吸收,返回高电平,读取相应IO口的电平就可以知道小车此时的大致位置;模块有四个输入接口,分别连接四个TT马达,驱动小车运动;

2301_81374681的博客 1万+

arcengine Icommand

转自:http://blog.youkuaiyun.com/hellolib/article/details/39293655 Built-in Commands, Menus and Toolsets The information in this document is useful if you are trying to programmatically use a built-in Contro

huluanchushou的专栏 4422

日语五十音图速记攻略:从形象联想法到实战训练

语言学习中的记忆编码与条件反射构建是高效掌握基础的关键。其核心原理在于通过将抽象符号与具象图像、故事或已知概念关联,利用大脑对视觉和叙事信息的天然高记忆效率,从而降低认知负荷,加速识别与反应速度。这一方法的技术价值在于将机械重复转化为意义联结,显著提升长期记忆的牢固度与提取速度。在日语学习这一具体应用场景中,五十音图作为表音文字系统,正是实践这一记忆技术的绝佳对象。通过系统化的形象联想、分组对比(如平假名与片假名的对应关系)以及间隔重复的实战训练,学习者可以高效攻克这一入门难关,为后续的词汇、语法学习铺设坚

weixin_29032489的博客 376

ICNN实现入侵检测的思路与源码(CIC-IDS-2017)

基于ICNN实现入侵检测,可用于现实网络

t1274171989的博客 8415

设计模式第19讲——命令模式(Command)

命令模式(Command Pattern)是一种行为型设计模式,又叫动作模式或事务模式。一、什么是命令模式 二、角色组成 三、优缺点 四、应用场景 4.1 生活场景4.2 java场景五、代码实现5.0 UML类图 5.1 抽象命令(Command)——Command5.2接收者(Receiver)——Chef5.3具体命令(Concrete Command)——OrderCommand六、总结

让~学习~成为一种习惯(橡 皮 人の技术博客) 1万+

实用电路精讲系列---双级运放放大电路(差分放大+跟随缓冲)

本文分析了双极运放放大电路的工作原理及其典型应用。该电路结合差分放大器和跟随缓冲器,实现高精度信号放大与阻抗匹配。差分放大器通过放大差模信号并抑制共模噪声提升信噪比;跟随缓冲器则提供阻抗变换,确保信号稳定传输。两者协同工作可优化输入阻抗、增强噪声抑制并提高设计灵活性。文章还列举了10个典型应用案例,包括医疗设备、工业传感器和新能源系统等,展示了该电路在精密电子系统中的关键作用。最后通过实用电路分析,详细说明了各模块功能及设计注意事项。

weixin_40590799的博客 2953

设计模式之【命令模式】,方法调用的花式玩法

命令模式(Command Pattern)是对命令的封装,每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式解耦了请求方和接收方,请求方只需请求执行命令,不用关心命令是怎样被接受,怎样被操作以及是否被执行等。命令模式属于行为型模式。原文:将一个请求封装成医德对象,从而让你使用不同的请求把客户端参数化,对请求排队或者记录请求日志,可以提供命令的撤销和恢复功能。在软件系统中,行为请求者与行为实现者通常是一种紧耦合关系,因为这样的实现简单明了。

秃了也弱了 3751

【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)

在游戏发展史上,有些游戏以其简单而耐玩的特性,深深地烙印在了玩家的记忆中。《黄金矿工》就是其中之一,它曾经在4399等游戏平台上掀起了一股游戏热潮。这款游戏不仅给无数玩家带来了欢乐,还让他们体验到了挖掘金矿的刺激与乐趣。在这个项目中,我们将花费半天的时间,利用Unity引擎,重新打造这款经典小游戏。通过复刻《黄金矿工》,我们不仅是在向童年的回忆致敬,更是在挖掘游戏设计的精髓。在这个过程中,我们将学习如何实现游戏的核心玩法,设计简洁而有效的游戏机制。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 2900

国债期货的日线趋势跟踪策略实现(基于backtrader框架)

通过backtrader框架,我们可以轻松地实现国债期货的日线趋势跟踪策略,并进行回测和验证。通过这种策略,我们可以尝试捕捉国债期货价格的短期趋势,并根据趋势的方向进行交易决策。backtrader提供了许多内置的指标、订单类型和其他功能,可以帮助你进一步优化和改进你的策略。它提供了丰富的工具和功能,使我们能够快速实现和验证我们的交易想法。方法中,我们根据当前价格和前一天的价格判断趋势的方向,并根据趋势的变化进行买入或卖出操作。然后,我们设置了初始资金和交易手续费,并将我们定义的策略。来跟踪每日的收盘价。

NisyPhilosophy的博客 404

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

命令模式是一种数据驱动的设计模式,它属于行为型模式。请求以命令的形式包裹在对象中,并传给调用对象。调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令。命令模式的主要优点是可以将请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化。主要解决在软件系统中,行为请求者与行为实现者通常是一种紧耦合的关系,但某些场合,比如需要对行为进行记录、撤销或重做、事务等处理时,这种无法抵御变化的紧耦合的设计就不太合适。

miaoyl的博客 2944

74、光谱成像在电子内窥镜及色彩理论中的应用

本文探讨了光谱成像在电子内窥镜中的应用及其与色彩理论的深度融合。通过分析FICE技术、色彩再现模型及胃黏膜光谱测量,展示了光谱信息在提升医学诊断准确性方面的潜力。同时,系统阐述了颜色的物理属性、标准表示方法、同色异谱现象、颜色测量技术(密度法与比色法)以及CIELAB等均匀颜色空间的构建原理。结合流程图与对比表格,梳理了从光信号获取到颜色处理的完整路径,并展望了人工智能与新型视觉模型在未来医疗成像与色彩科学中的发展方向。

g2h3i4j5的博客 152

Java设计模式 Design Pattern:命令模式 Command Pattern

Java设计模式 Design Pattern:命令模式 Command Pattern 目的 Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support un...

ahch8077的博客 164

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

设计模式-命令模式-Command Pattern

创建一个命令接口,它包含执行操作的方法(如。

wesigj的博客 2031

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

23种设计模式之命令模式(Command Pattern)

大家好,我是小威,24届毕业生,在一家满意的公司实习。命令模式,此篇文章为一天学习一个设计模式系列文章,后面会分享其他模式知识。

小威的博客 2万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

秒懂设计模式之命令模式(Command Pattern)

[版权申明] 非商业目的注明出处可自由转载 博文地址:https://blog.youkuaiyun.com/ShuSheng0007/article/details/116035276 出自:shusheng007 设计模式汇总篇,一定要收藏: 永不磨灭的设计模式(有这一篇真够了,拒绝标题党) 文章目录概述类型难度定义使用场景UML实例第一步:声明一个命令接口 (Command)第二步:构建那些可以具体完成命令的角色(Receiver)第三步:构建各种具体命令(ConcreteCommand)第四步:构建命令的调.

ShuSheng007的程序人生 3321

设计模式(十五)——命令模式(Command Pattern)

命令模式(Command Pattern) 基本介绍 命令模式:将一一个请求封装为一一个对象,从而使我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。也称之为:动作Action模式、事务transaction模式。 命名模式使得请求发送者与请求接收者消除彼此之间的耦合,让对象之间的调用关系更加灵活,实现解耦。 在命名模式中,会将一个请求封装为一个对象,以便使用...

Duktig的博客 369

设计模式教程:命令模式(Command Pattern)

将请求封装成一个对象,从而使您可以用不同的请求对客户进行参数化,将请求排队或记录日志,以及支持撤销操作

遇见伯灵说的博客 2035

23种设计模式——命令模式(Command Pattern)

本文介绍了23种经典设计模式之——命令模式(Command Pattern)的使用及说明

Meteors.的博客 688

设计模式:命令模式(Command Pattern)

/** * 命令模式。 * @author Bright Lee */ public class CommandPattern { public static void main(String[] args) { Receiver receiver = new Receiver(); Command cmd001 = new OnCommand(receiver); C...

look4liming的专栏 273

设计模式|命令模式(Command Pattern)

命令模式(Command Pattern)是一种行为设计模式,它允许将请求封装成对象,从而使你可以参数化其他对象对请求的执行。在命令模式中,请求的发送者和接收者之间不直接交互,而是通过一个命令对象来解耦。这使得请求发送者无需知道请求的具体操作或者接收者,从而增强了系统的灵活性和可扩展性。

weixin_44435110的博客 2001

[Design Pattern] Command Pattern 命令模式

发现公司的代码好像有用到 Command Pattern,回顾重温下。 Command Pattern 的类图结构如下: 参考 《Head First Design Patterns(英文版)》P245 绘制 我所理解的 Command Pattern 如图。 caller, action, subject 分别对于类图中的 Invoker, Command, ...

QQ562224896的博客 138

设计模式(Design pattern)之命令模式(Command Pattern)

命令模式是一种行为型设计模式,通过将请求封装为对象来实现参数化客户端操作。本文以餐厅点餐为例,展示了命令模式的具体实现:Order类封装订单信息,Cook类作为命令执行者,Waiter类作为调用者,Command接口定义执行方法。OrderCommand实现类将订单和厨师关联,当服务员调用sayOrder()时,会依次执行所有命令对象,触发厨师制作菜品。这种模式实现了请求发送者和接收者的解耦,支持命令的排队、记录和撤销操作。示例中01桌和02桌的订单被封装为命令对象,由服务员统一触发执行,演示了命令模式在实

RR1335 之代码才是动力源 236

Java设计模式——命令模式【Command Pattern】

Java设计模式、命令模式、Command Pattern

scorpio的博客 1039

设计模式之命令模式(Command Pattern)

文章目录一、概念二、命令模式的UML类图三、命令模式的应用实例:智能家电项目3.1、项目介绍3.2、项目UML类图3.3、代码3.3.1、 Command(命令):Command3.3.2、Receiver(接收者):LightReceiver3.3.3、ConcreteCommand(命令的实现类):3.3.4、Invoker(请求者): RemoteController3.3.5、Client...

猎人在吃肉 773
上一篇: 设计模式——单件模式(Singleton Pattern)
下一篇: 设计模式——适配器模式(Adapter Pattern)
蜗牛lz
博客等级 码龄15年 17粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值