命令模式(Command Pattern)

embedded/2024/9/24 6:20:56/

命令模式(Command Pattern)是一种行为设计模式,它将一个请求封装为一个对象,从而使你可以使用不同的请求、队列或日志来参数化对象。命令模式让你可以在不修改调用对象的情况下将请求排队、记录日志或撤销操作。

核心思想:

  • 命令对象:将请求和其所有相关的参数封装到一个对象中。
  • 调用者:负责触发命令执行。
  • 接收者:负责执行具体的命令逻辑。
  • 优点命令模式可以实现命令的撤销、重做、排队执行等功能。

关键组成:

  1. Command 接口:定义了一个执行命令的接口。
  2. 具体命令类:实现了 Command 接口,负责将请求委托给接收者执行。
  3. 接收者:实际执行命令操作的对象。
  4. 调用者:通过命令对象来执行请求,不需要直接调用接收者。

场景示例:家庭自动化系统

假设我们有一个家庭自动化系统,能够通过遥控器控制各种设备,比如灯和音响。我们将通过命令模式封装打开/关闭设备的操作。

代码实现:

1. 创建命令接口 Command

Command 接口定义了所有命令都必须实现的 execute() 方法。

java">public interface Command {void execute();void undo();  // 增加撤销功能
}
2. 创建接收者类

这些类代表具体的设备,如灯 (Light) 和音响 (Stereo),它们包含打开和关闭的具体操作。

2.1 Light
java">public class Light {public void on() {System.out.println("The light is on");}public void off() {System.out.println("The light is off");}
}
2.2 Stereo
java">public class Stereo {public void on() {System.out.println("The stereo is on");}public void off() {System.out.println("The stereo is off");}public void setCD() {System.out.println("CD is set in stereo");}public void setVolume(int volume) {System.out.println("Stereo volume set to " + volume);}
}
3. 创建具体的命令类

每个具体命令类都实现 Command 接口,将请求传递给对应的接收者对象执行。

3.1 LightOnCommand
java">public class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.on();}@Overridepublic void undo() {light.off();}
}
3.2 LightOffCommand
java">public class LightOffCommand implements Command {private Light light;public LightOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.off();}@Overridepublic void undo() {light.on();}
}
3.3 StereoOnCommand
java">public class StereoOnCommand implements Command {private Stereo stereo;public StereoOnCommand(Stereo stereo) {this.stereo = stereo;}@Overridepublic void execute() {stereo.on();stereo.setCD();stereo.setVolume(10);}@Overridepublic void undo() {stereo.off();}
}
3.4 StereoOffCommand
java">public class StereoOffCommand implements Command {private Stereo stereo;public StereoOffCommand(Stereo stereo) {this.stereo = stereo;}@Overridepublic void execute() {stereo.off();}@Overridepublic void undo() {stereo.on();stereo.setCD();stereo.setVolume(10);}
}
4. 创建调用者类 RemoteControl

RemoteControl 作为调用者,保存命令对象并执行它们。

java">public class RemoteControl {private Command[] onCommands;private Command[] offCommands;private Command undoCommand;public RemoteControl() {onCommands = new Command[7];offCommands = new Command[7];Command noCommand = new NoCommand(); // 空命令,避免 null 检查for (int i = 0; i < 7; i++) {onCommands[i] = noCommand;offCommands[i] = noCommand;}undoCommand = noCommand;}public void setCommand(int slot, Command onCommand, Command offCommand) {onCommands[slot] = onCommand;offCommands[slot] = offCommand;}public void onButtonWasPressed(int slot) {onCommands[slot].execute();undoCommand = onCommands[slot];}public void offButtonWasPressed(int slot) {offCommands[slot].execute();undoCommand = offCommands[slot];}public void undoButtonWasPressed() {undoCommand.undo();}
}
5. 创建空命令 NoCommand

命令模式用于初始化每个命令插槽,防止出现 null 检查。

java">public class NoCommand implements Command {@Overridepublic void execute() {// 什么也不做}@Overridepublic void undo() {// 什么也不做}
}
6. 测试客户端

客户端测试如何通过命令模式控制设备。

java">public class RemoteControlTest {public static void main(String[] args) {RemoteControl remoteControl = new RemoteControl();// 创建接收者Light livingRoomLight = new Light();Stereo stereo = new Stereo();// 创建命令对象LightOnCommand lightOn = new LightOnCommand(livingRoomLight);LightOffCommand lightOff = new LightOffCommand(livingRoomLight);StereoOnCommand stereoOn = new StereoOnCommand(stereo);StereoOffCommand stereoOff = new StereoOffCommand(stereo);// 将命令对象设置到遥控器中remoteControl.setCommand(0, lightOn, lightOff);remoteControl.setCommand(1, stereoOn, stereoOff);// 模拟按钮按下System.out.println("Turning on the light...");remoteControl.onButtonWasPressed(0);System.out.println("Turning off the light...");remoteControl.offButtonWasPressed(0);System.out.println("Undoing the last command...");remoteControl.undoButtonWasPressed();System.out.println("Turning on the stereo...");remoteControl.onButtonWasPressed(1);System.out.println("Turning off the stereo...");remoteControl.offButtonWasPressed(1);}
}

输出结果

Turning on the light...
The light is on
Turning off the light...
The light is off
Undoing the last command...
The light is on
Turning on the stereo...
The stereo is on
CD is set in stereo
Stereo volume set to 10
Turning off the stereo...
The stereo is off

代码解释

  1. 命令接口 Command:定义了命令的基本操作,包含 execute()undo() 方法。
  2. 具体命令类:实现了 Command 接口,负责调用接收者执行具体的命令操作。每个命令类负责一个具体的任务,如打开或关闭灯、打开或关闭音响等。
  3. 接收者类:如 LightStereo,这些类包含实际的业务逻辑。
  4. 调用者 RemoteControl:保存和调用命令对象,通过按钮调用 onCommandoffCommand
  5. 空命令 NoCommand:用来初始化按钮插槽,避免空指针异常。

优点

  • 松耦合:调用者和接收者之间通过命令对象解耦,调用者无需关心具体的业务实现。
  • 扩展性:可以轻松添加新的命令类而不影响其他类的代码。
  • 支持撤销和重做命令模式通过封装命令对象,使得支持撤销和重做功能变得容易。

适用场景

  • 需要参数化对象以执行不同的请求。
  • 需要在不改变调用代码的情况下记录命令、撤销或排队执行命令。
  • 需要将操作封装为对象以便进行传递、记录、或回放。

通过命令模式,可以灵活地对操作进行解耦,适用于复杂系统中对操作的管理。


http://www.ppmy.cn/embedded/109930.html

相关文章

利用深度学习实现验证码识别-4-ResNet18+imagecaptcha

在当今的数字化世界中&#xff0c;验证码&#xff08;CAPTCHA&#xff09;是保护网站免受自动化攻击的重要工具。然而&#xff0c;对于用户来说&#xff0c;验证码有时可能会成为一种烦恼。为了解决这个问题&#xff0c;我们可以利用深度学习技术来自动识别验证码&#xff0c;从…

【CSS】mask-image属性的详细介绍

mask-image属性是CSS中一个用于指定元素遮罩图像的属性。它允许开发者通过图像来遮罩元素的背景或其他图像内容&#xff0c;实现复杂的视觉效果。以下是对mask-image属性的详细介绍&#xff1a; 一、属性定义 mask-image属性定义了一个图像的遮罩层&#xff0c;该遮罩层将应用…

Java——踩坑Arrays.asList()

坑1&#xff1a;不能直接使用 Arrsys.asList() 来转换基本类型数据 public static void test1(){// 1、不能直接使用asList来转换基本类型数组int[] arr {1, 2, 3};List list Arrays.asList(arr);System.out.printf("list:%s size:%s class:%s", list, list.size(…

Docker Elasticsearch安装ik分词插件教程

本章教程在通过Docker 安装Elasticsearch,并安装ik分词插件。本文的重点是安装ik分词插件。 一、安装Elasticsearch 安装教程以前写过,参考:https://blog.csdn.net/qq_19309473/article/details/140725121 安装之后,通过http://ip:9200,可以访问,就表示安装成功。 二、安装…

【专题】2024年8月中国企业跨境、出海、国际化、全球化行业报告汇总PDF合集分享(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p37584 在全球化浪潮汹涌澎湃的当下&#xff0c;中国企业积极探索海外市场&#xff0c;开启了出海跨境的新征程。本报告合集旨在全面梳理出海跨境全球化行业的发展态势&#xff0c;涵盖多个领域的深度洞察。 从游戏、快消品、医疗器…

大学生必看干货!分享5款ai写毕业论文软件

在当今数字化时代&#xff0c;AI写作工具已经成为大学生撰写毕业论文的重要辅助手段。这些工具不仅能够提高写作效率&#xff0c;还能帮助学生生成高质量的文稿。以下是五款备受推荐的AI写毕业论文软件&#xff0c;其中特别推荐千笔-AIPassPaper。 ### 1. 千笔-AIPassPaper 传…

[C++#33][异常] 错误码 | 抛出与捕获 | 异常安全 | 异常体系

目录 C语言与C错误处理方式的对比及应用 一、C语言传统的错误处理方式 1. 终止程序&#xff1a;assert 2. 返回错误码 缺点&#xff1a; 二、C中的异常处理机制 1. 基本概念 2. 异常的抛出与捕获 3. 异常的重新抛出 三、C中的异常安全 1. 构造函数与析构函数的异常 …

Java证书信息收集

1.Java二级 【NCRE 二级Java语言程序设计02】考试流程及二级Java大纲_java语言程序设计计算机二级-CSDN博客