设计模式-命令模式

文章目录

  • 前言
  • 命令模式简介
  • 命令模式的示例代码
  • 命令模式使用场景
  • 命令模式优缺点

前言

命令模式(Command Pattern)是一种行为型设计模式,用于将请求发送者和请求接收者解耦,使得可以在不同的上下文中灵活地传递请求,记录请求日志,撤销请求等操作。本文将介绍命令模式的概念,以及如何使用Java代码来实现它。

命令模式简介

在软件设计中,命令模式是一个非常有用的模式,它将请求封装为一个对象,从而允许我们参数化不同的对象、将请求排队或记录请求日志,并支持撤销操作。

命令模式通常涉及以下几个角色:

  1. 命令接口(Command Interface): 定义了命令的接口,通常包括一个执行命令的方法。

  2. 具体命令(Concrete Command): 实现了命令接口,负责具体的命令逻辑。它包含了一个接收者对象,该对象实际执行命令。

  3. 接收者(Receiver): 执行实际工作的对象。它知道如何执行命令相关的操作。

  4. 调用者(Invoker): 发送命令的对象,它包含了命令对象,并在需要时触发命令的执行。

命令模式的示例代码

让我们通过一个简单的示例来演示命令模式的使用。假设我们有一个遥控器,可以控制不同的电器设备,例如电灯和音响。我们希望通过遥控器发送不同的命令来控制这些设备。

首先,我们定义命令接口 Command

// 命令接口
public interface Command {void execute();
}

然后,我们创建具体的命令类,例如控制电灯和音响的命令:

// 具体命令 - 控制电灯
public class LightOnCommand implements Command {private Light light;public LightOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.turnOn();}
}// 具体命令 - 控制音响
public class StereoOnCommand implements Command {private Stereo stereo;public StereoOnCommand(Stereo stereo) {this.stereo = stereo;}@Overridepublic void execute() {stereo.turnOn();}
}

接着,我们定义电器设备的接收者类,例如电灯和音响:

// 电灯 - 接收者
public class Light {public void turnOn() {System.out.println("Light is ON");}public void turnOff() {System.out.println("Light is OFF");}
}// 音响 - 接收者
public class Stereo {public void turnOn() {System.out.println("Stereo is ON");}public void turnOff() {System.out.println("Stereo is OFF");}
}

最后,我们创建调用者类 RemoteControl,它可以将命令与具体的电器设备关联并触发命令的执行:

// 调用者 - 遥控器
public class RemoteControl {private Command command;public void setCommand(Command command) {this.command = command;}public void pressButton() {command.execute();}
}

现在,我们可以使用命令模式来控制电灯和音响:

public class CommandPatternExample {public static void main(String[] args) {// 创建电灯和音响对象Light light = new Light();Stereo stereo = new Stereo();// 创建具体命令对象并关联接收者Command lightOn = new LightOnCommand(light);Command stereoOn = new StereoOnCommand(stereo);// 创建遥控器RemoteControl remote = new RemoteControl();// 设置命令并触发执行remote.setCommand(lightOn);remote.pressButton();remote.setCommand(stereoOn);remote.pressButton();}
}

运行上述代码,你将看到电灯和音响分别被打开,这是通过命令模式将具体的命令对象与接收者关联并执行的。

命令模式使用场景

命令模式在以下场景中非常有用:

  1. 请求发送者和接收者解耦: 当需要将请求的发送者和接收者解耦时,命令模式非常有用。发送者不需要知道接收者的具体实现,只需与命令对象交互。

  2. 支持撤销和重做操作: 命令模式可以轻松支持撤销和重做操作。每个命令对象可以保存执行前的状态,以便在需要时撤销或重做操作。

  3. 请求排队和调度: 命令模式可以用于构建命令队列,从而支持请求的排队和调度。这在任务调度和线程池等场景中非常有用。

  4. 日志和事务系统: 在需要记录请求日志或构建事务系统时,命令模式可以记录每个执行的命令,从而支持日志记录和事务回滚。

  5. 遥控器和按钮控制: 命令模式常常用于创建遥控器和按钮控制系统,其中每个按钮代表一个命令,可以轻松地添加新的命令和按钮。

  6. 菜单系统: 在图形用户界面中,命令模式可用于创建菜单和工具栏系统。每个菜单项或工具按钮都可以关联一个命令对象来执行相应的操作。

  7. 自动化系统: 在自动化系统中,命令模式可以用于创建脚本和自动化任务,通过命令对象来执行各种操作。

  8. 游戏开发: 命令模式可以用于游戏中的玩家操作,将玩家的输入转化为游戏内的命令。

  9. 电子设备遥控器: 电视遥控器、音响遥控器等都可以使用命令模式来实现。

  10. 多级菜单和导航: 当需要构建多级嵌套的菜单和导航系统时,命令模式可以用于处理用户的交互操作。

总之,命令模式适用于任何需要将请求封装为对象、支持撤销和重做、解耦请求发送者和接收者、支持请求排队和调度、以及记录请求日志等情景。它提供了一种优雅的方式来处理请求和操作,增强了代码的可维护性和可扩展性。

命令模式优缺点

命令模式是一种有用的设计模式,它具有一些优点和缺点,下面是它们的总结:

优点:

  1. 解耦发送者和接收者: 命令模式将请求发送者和请求接收者解耦,发送者不需要知道接收者的具体实现,从而提高了系统的灵活性和可维护性。

  2. 支持撤销和重做: 命令模式支持撤销和重做操作,每个命令对象可以保存执行前的状态,允许在需要时撤销或重做操作。

  3. 支持事务性操作: 命令模式可以用于构建事务系统,多个命令可以组合成一个事务,要么全部执行成功,要么全部回滚。

  4. 容易扩展新命令: 可以轻松地添加新的命令类和请求,无需修改现有的代码,增加了系统的可扩展性。

  5. 支持命令队列: 命令模式可以用于构建命令队列,支持请求的排队和调度,有助于任务调度和线程池的实现。

  6. 日志和审计: 命令模式可以用于记录请求日志,对于系统的监控和审计非常有用。

缺点:

  1. 增加了类和对象的数量: 命令模式引入了大量的命令类和具体命令对象,可能会导致类的数量激增,增加了系统的复杂性。

  2. 可能引入过多的细粒度命令: 如果设计不当,可能会引入过多的细粒度命令类,使代码难以理解和维护。

  3. 不适用于所有情况: 命令模式适用于需要将请求封装为对象、支持撤销和重做、解耦发送者和接收者的情况,但并不是所有情况都适合使用命令模式。

  4. 性能开销: 命令模式可能会引入一定的性能开销,因为每个命令都需要创建一个具体命令对象和执行它。

  5. 复杂性增加: 如果命令模式被不合理地设计或使用,可能会增加系统的复杂性,使代码难以理解和维护。

综上所述,命令模式在需要支持撤销、重做、记录日志等功能的场景中非常有用,但在使用时需要谨慎设计和管理,以确保权衡好优点和缺点,并满足具体需求。它在构建交互式应用、事务处理系统和工作流引擎等方面发挥了重要作用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/76460.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Gin中的Cookie和Session的用法

Gin中的Cookie和Session的用法 文章目录 Gin中的Cookie和Session的用法介绍Cookie代码演示 Session代码展示 介绍 cookie 和 session 是 Web 开发中常用的两种技术,主要用于跟踪用户的状态信息。 Cookie func (c *Context) Cookie(name string, value string, max…

java Math类中的random方法和Random类中方法的区别

文章目录 Math类中的random()方法Random类 Math类中的random()方法 Math类中的random()方法没有参数,它会默认返回等于0.0、小于1.0的double类型随机数。对double()方法返回的数字稍加处理,即可实现任意范围随机数的功能 public class MathTest {publi…

vue 前端 问题整理

列表显示字典数据 template里面的vue代码 <el-table-column label"性别" align"center" prop"sex"><template #default"scope"> <!-- <dict-tag :optionssysUserSex :value"scope.row.sex&quo…

Redis持久化、主从与哨兵架构详解

Redis持久化 RDB快照&#xff08;snapshot&#xff09; 在默认情况下&#xff0c; Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。 你可以对 Redis 进行设置&#xff0c; 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时&#xff0c; 自动保存一次数…

【Linux】让笔记本发挥余热,Ubuntu20.04设置WiFi热点

Ubuntu20.04设置WiFi热点 由于卧室距离客厅较远&#xff0c;wifi信号太弱&#xff0c;体验极差。鉴于卧室的笔记本电脑是通过网线连接的客厅路由器&#xff0c;因此考虑将这台老破笔记本作为“路由器”&#xff0c;以便发挥它的余热。实验证明&#xff0c;上网速度提升数十倍&a…

Kubectl 使用详解——k8s陈述式资源管理

目录 一、kubectl 简介 二、kubectl 的使用 1.基础用法 &#xff08;1&#xff09;配置kubectl自动补全 &#xff08;2&#xff09;查看版本信息 &#xff08;3&#xff09;查看资源对象信息 &#xff08;4&#xff09;查看集群信息 &#xff08;5&#xff09;查看日志…

taro vue3 ts nut-ui 项目

# 使用 npm 安装 CLI $ npm install -g tarojs/cli 查看 Taro 全部版本信息​ 可以使用 npm info 查看 Taro 版本信息&#xff0c;在这里你可以看到当前最新版本 npm info tarojs/cli 项目初始化​ 使用命令创建模板项目&#xff1a; taro init 项目名 taro init myApp …

英飞凌TC3xx--深度手撕HSM安全启动(三)--TC3xx HSM系统架构

今天聊TC3xx HSM系统,包括所用内核、UCB相关信息、Host和HSM交互方式。 1、HSM系统架构 下图来源于英飞凌官网培训材料。 TC3xx的HSM内核是一颗32位的ARM Cortex M3,主频可达100MHz,支持对称算法AES128、非对称算法PKC(Public Key Crypto) ECC256、Hash SHA2,以及T…

算法通关村第十七关:白银挑战-贪心高频问题

白银挑战-贪心高频问题 1. 区间问题 所有的区间问题&#xff0c;参考下面这张图 1.1 判断区间是否重叠 LeetCode252 https://leetcode.cn/problems/meeting-rooms/ 思路分析 因为一个人在同一时刻只能参加一个会议&#xff0c;因此题目的本质是判断是否存在重叠区间 将区…

30天入门Python(基础篇)——第2天:Python安装(保姆级)与IDE的认识与选择+详细安装教程

文章目录 专栏导读上一节课回顾1、Python解释器的安装查看各个版本的Python解释器①、ok,双击安装②、这里我们选择【自定义】安装&#xff0c; 下面的【将Python添加在环境变量】大家一定要打个勾③、点击【Next】进行下一步④、这里不建议安装在C盘, 点击【Browse】我在F盘创…

Java——》公平锁、非公平锁

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…

C++ 多态

引例&#xff1a; #include<iostream> using namespace std; class Animal { public:void speak(){cout<<"动物在说话"<<endl;} }; class Cat:public Animal { public:void speak(){cout<<"小猫在说话"<<endl;} }; void Do…

Element U I的 el-date-picker做时间限制

Element U I的 el-date-picker做时间限制 Element U I的 el-date-picker做时间限制 Element U I的 el-date-picker做时间限制 ###公司需要限制起始时间为今年的第一天。 特定的时间 干脆写死得了&#xff01; 最有用的就是下面这句&#xff1a; disabledDate(time) { // 这个是…

多线程和并发编程(2)—CAS和Atomic实现的非阻塞同步

在并发编程中实现原子操作可以使用锁&#xff0c;锁机制满足基本的需求是没有问题的了&#xff0c;但是有的时候我们的需求并非这么简单&#xff0c;我们需要更有效&#xff0c;更加灵活的机制&#xff0c;synchronized关键字是基于阻塞的锁机制&#xff0c;也就是说当一个线程…

CSS整理

目录 CSS中的& 弹性&#xff08;display:flex&#xff09;布局 flex的对齐方式 justify-content align-items flex-wrap 弹性盒换行 flex:1 flex属性 flex-grow&#xff1a;项目的放大比例 flex-shrink&#xff1a;收缩 flex-basis&#xff1a;初始值&#xff…

从零开始学习 Java:简单易懂的入门指南之HashMap及TreeMap源码解读(二十四)

HashMap及TreeMap源码解读 HashMap源码TreeMap源码 HashMap源码 1.看源码之前需要了解的一些内容Node<K,V>[] table 哈希表结构中数组的名字DEFAULT_INITIAL_CAPACITY&#xff1a; 数组默认长度16DEFAULT_LOAD_FACTOR&#xff1a; 默认加载因子0.75HashMap里…

GE IS220PAICH2A 336A4940CSP11 数字量输入模块产品应用领域

GE IS220PAICH2A 336A4940CSP11 是一款数字量输入模块&#xff0c;通常用于工业自动化和控制系统中&#xff0c;用于监测和采集数字输入信号。这种类型的模块可以在各种应用领域中发挥作用&#xff0c;以下是一些可能的应用领域&#xff1a; 工业过程控制&#xff1a; GE IS220…

count(*) 和 count(1) 有什么区别?哪个性能最好?

哪种 count 性能最好&#xff1f; count() 是什么&#xff1f; count() 是一个聚合函数&#xff0c;函数的参数不仅可以是字段名&#xff0c;也可以是其他任意表达式&#xff0c;该函数的作用是统计符合查询条件的记录中&#xff0c;函数指定的参数不为 NULL 的记录由多少条。…

openpnp - 二手西门子电动飞达 - 物料编带安装的正确姿势

文章目录 openpnp - 二手西门子电动飞达 - 物料编带安装的正确姿势概述将料头用接料引带加长接料引带的规格将编带送入飞达的编带导引槽物料正常载入完成的子飞达没有错误指示灯END openpnp - 二手西门子电动飞达 - 物料编带安装的正确姿势 概述 手头一堆2手的西门子电动飞达…

盲打键盘的正确指法指南

简介 很多打字初学者&#xff0c;并不了解打字的正确指法规范&#xff0c;很容易出现只用两根手指交替按压键盘的“二指禅”情况。虽然这样也能实现打字&#xff0c;但是效率极低。本文将简单介绍盲打键盘的正确指法&#xff0c;以便大家在后续的学习和工作中能够提高工作效率…