设计模式之命令模式

server/2024/11/15 5:40:40/

一、详细介绍

        命令模式是一种行为型设计模式它将“请求”封装为一个对象,使得使用请求、参数化请求、队列请求、撤销请求、日志请求等多种请求变得简单。命令模式通过将“行为请求者”与“行为实现者”解耦,使得请求的发送者和接收者完全分离,实现命令的发送者与执行者之间的解耦。

命令模式包含以下几个关键角色

  1. 命令接口(Command):定义命令的公共接口,声明执行命令的抽象方法。

  2. 具体命令(Concrete Command):实现命令接口,绑定一个接收者对象,并实现命令接口中声明的执行方法,负责调用接收者的相应操作方法。

  3. 接收者(Receiver):负责执行命令请求的具体操作,是命令的真正执行者。

  4. 调用者(Invoker):负责调用命令对象的执行方法,与命令对象之间通过命令接口交互,不关心命令的具体实现。

二、使用场景

  1. 需要将请求调用者与请求接收者解耦:通过命令模式,调用者无需了解接收者的具体实现,只需调用命令对象的执行方法。

  2. 需要支持命令的撤销/重做操作:命令对象可以记录其执行状态,方便实现撤销和重做功能。

  3. 需要支持命令队列:可以将命令对象放入队列中,按照一定顺序依次执行。

  4. 需要支持日志记录、事务操作等:通过命令对象记录操作历史,便于回溯和审计。

三、注意事项

  1. 命令接口的设计:命令接口应尽可能简洁,只包含必要的执行方法,避免引入过多的复杂性。

  2. 命令对象的生命周期管理:确保在适当的时候创建、执行、撤销命令对象,避免资源泄露。

  3. 命令对象的线程安全:如果命令对象在多线程环境中使用,需要考虑线程安全问题。

四、优缺点

优点:

  1. 降低对象之间的耦合度:调用者与接收者之间通过命令对象进行交互,二者之间无需直接依赖。

  2. 支持命令的撤销/重做:命令对象可以记录其执行状态,便于实现撤销和重做功能。

  3. 易于扩展新的命令:只需增加新的具体命令类,符合开闭原则。

缺点:

  1. 命令类数量可能会过多:如果系统中命令类型较多,可能会导致命令类数量增长较快。

  2. 命令模式可能会增加系统的复杂性:引入额外的命令、接收者、调用者等类,增加了系统的理解和维护难度。

五、Java代码示例

以下是一个简单的Java代码示例,展示了使用命令模式控制家电设备:

// 命令接口(Command)
interface Command {void execute();
}// 具体命令(Concrete Command)
class TurnOnCommand implements Command {private final ElectricDevice device;public TurnOnCommand(ElectricDevice device) {this.device = device;}@Overridepublic void execute() {device.turnOn();}
}class TurnOffCommand implements Command {private final ElectricDevice device;public TurnOffCommand(ElectricDevice device) {this.device = device;}@Overridepublic void execute() {device.turnOff();}
}// 接收者(Receiver)
class ElectricDevice {public void turnOn() {System.out.println("Electric device turned on.");}public void turnOff() {System.out.println("Electric device turned off.");}
}// 调用者(Invoker)
class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}
}// 客户端代码
public class Client {public static void main(String[] args) {ElectricDevice device = new ElectricDevice();RemoteControl remote = new RemoteControl();Command turnOnCommand = new TurnOnCommand(device);Command turnOffCommand = new TurnOffCommand(device);remote.setCommand(turnOnCommand);remote.pressButton(); // Output: Electric device turned on.remote.setCommand(turnOffCommand);remote.pressButton(); // Output: Electric device turned off.}
}

六、问题与解决方案

  1. 命令对象过多导致管理困难:可以使用工厂模式、注册表模式等来集中管理和创建命令对象。

  2. 命令对象的撤销/重做功能实现复杂:可以为命令接口添加undo()redo()方法,并在具体命令中实现这些方法。如果撤销/重做操作较复杂,可以考虑使用备忘录模式辅助实现。

七、与其他模式的对比

  1. 与策略模式的对比:策略模式强调算法或行为的替换,命令模式强调请求的封装和解耦。策略模式中的上下文直接使用策略对象,而命令模式中的调用者通过命令对象间接调用接收者。

  2. 与观察者模式的对比:观察者模式关注对象状态变化的通知,命令模式关注请求的封装和解耦。观察者模式中观察者被动接收通知,命令模式中调用者主动调用命令。

  3. 与模板方法模式的对比:模板方法模式定义了算法骨架,子类填充具体步骤。命令模式中命令对象执行的是完整的行为请求,而非算法的一部分。


http://www.ppmy.cn/server/18275.html

相关文章

vue的v-model、v-if、v-for用react语法实现

在React中,没有直接对应于Vue中的v-model、v-if和v-for的指令,但你可以使用React的特性和组件来实现类似的功能。 1. v-model 在Vue中,v-model用于在表单元素和组件之间创建双向数据绑定。在React中,你可以使用受控组件&#xf…

【bug】vuxUI组件popup弹出框在IOS中遮罩层会遮住页面

可以增加自定义方法v-transfer-dom <div v-transfer-dom"true"><Popup v-model"showPopup"><PopupHeader :title"policyloan.docJson.title" /><div class"noticeText"><p v-for"(item, index) in po…

人脸识别开发项目汇总

1.基于FaceX-Zoo实现的人脸识别系统-CSDN博客 2.人脸识别&#xff1a;京东开源FaceX-Zoo&#xff1a;PyTorch工具箱 - 知乎 (zhihu.com) 3.人头识别-人群中准确快速的检测头部算法_在输入图像中检测人像头部的方法-CSDN博客 4.Github开源人脸识别项目face_recognition - 知乎…

SpringBoot:SpringMVC(下)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、RequestBody补充二、PathVariable三.RequestPart:四.ResponseBody五.CookieValue&#xff0c;SessionAttribute&#xff0c;RequestHeader 前言 提示&…

贪心(贪婪)算法

主要思想 贪心算法的思想主要可以概括为“总是做出当前看起来最优的选择”&#xff0c;也就是不从整体上进行考虑&#xff0c;所得到的答案是某种意义上的局部最优解&#xff0c;不一定是整体最优解。 贪心算法没有固定算法框架&#xff0c;算法设计的关键是贪心策略的选择。…

HarmonyOS开发:【基于命令行(开发环境)】

准备开发环境 在嵌入式开发中&#xff0c;很多开发者习惯于使用Windows进行代码的编辑&#xff0c;比如使用Windows的Visual Studio Code进行OpenHarmony代码的开发。但当前阶段&#xff0c;大部分的开发板源码还不支持在Windows环境下进行编译&#xff0c;如Hi3861、Hi3516系…

Linux——网络管理nmcli

nmcli 不能独立使用&#xff0c;需要对应的服务启动 1. NetworkManager.service 2. 网络配置和服务不相关 3. 通过 nmcl &#xff49; 建立网络配置和网卡之前的映射关系 网卡 简称&#xff1a;nmcli d DEVICE &#xff1a;物理设备 TYPE: 物理设备类型 ethernet 以太网…

动态内存管理 柔性数组

文章目录 动态内存函数 malloc freecallocrealloc 重新开辟空间realloc 也可以第一个参数为NULL&#xff0c;则是直接开辟内存&#xff0c;类似于malloc用法 常见的动态内存错误对空指针进行解引用操作对开辟的内存越界访问对非动态开辟的内存使用free释放使用free释放动态开辟…