设计模式:命令模式

命令模式(Command Pattern)是一种行为设计模式,它将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。

定义

命令模式包括以下主要角色:

  • Command:命令接口,声明执行操作的方法。
  • ConcreteCommand:具体命令,实现命令接口,定义绑定于接收者的动作。
  • Client:客户端,创建一个具体命令对象并设定其接收者。
  • Invoker:请求者,负责调用命令对象执行请求。
  • Receiver:接收者,执行与请求相关的操作。

应用场景

命令模式适用于以下场景:

  • 需要参数化对象根据不同请求执行不同操作时。
  • 需要在不同的时间指定、排队和执行请求时。
  • 需要支持撤销操作。
  • 需要支持日志变化,以及在系统崩溃时恢复这些变化。

示例

以下是一个简单的命令模式实现示例:

// Command接口
public interface Command {void execute();
}// Receiver类
public class Light {public void turnOn() {System.out.println("The light is on");}public void turnOff() {System.out.println("The light is off");}
}// ConcreteCommand类
public class TurnOnCommand implements Command {private Light light;public TurnOnCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.turnOn();}
}public class TurnOffCommand implements Command {private Light light;public TurnOffCommand(Light light) {this.light = light;}@Overridepublic void execute() {light.turnOff();}
}// Invoker类
public 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) {Light light = new Light();Command turnOn = new TurnOnCommand(light);Command turnOff = new TurnOffCommand(light);RemoteControl remote = new RemoteControl();remote.setCommand(turnOn);remote.pressButton();remote.setCommand(turnOff);remote.pressButton();}
}

反例

  • 如果系统中的命令非常简单,不需要撤销、日志记录等功能,使用命令模式可能会导致不必要的复杂性。
  • 如果每个命令只有一个接收者,并且具体的命令操作与接收者的方法一一对应,那么命令模式可能不会带来额外的好处。

原则间的权衡与冲突

命令模式通常遵循开闭原则(对扩展开放,对修改封闭),因为你可以引入新的ConcreteCommand类而不改变现有代码。然而,如果需要添加新的操作和请求,可能需要修改InvokerClient的代码,这可能与开闭原则冲突。

设计模式的局限性

  • 命令模式可能会导致某些系统中类的数量增加,每个操作都需要一个具体的命令类。
  • 对于简单的系统,引入命令模式可能会引起过度设计。

总结与建议

命令模式很有用,特别是在需要撤销操作、操作的排队、日志记录或事务功能时。在设计系统时,如果你预见到需要这些功能,那么采用命令模式是合理的。然而,在决定是否使用命令模式时,应该考虑系统的复杂性和可维护性。如果系统简单,且没有可撤销或宏命令的需求,则可以考虑更直接的方法来实现需求,避免不必要的复杂性。

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

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

相关文章

C语言程序与设计——工程项目开发

之前我们已经了解了C语言的基础知识部分,掌握这些之后,基本就可以开发一些小程序了。在开发时,就会出现合作的情况,C语言是如何协作开发的呢,将在这一篇文章进行演示。 工程项目开发 在开发过程中,你接到…

LeetCode 1. Two Sum

LeetCode 1. Two Sum 题目描述 给定一个整数数组 nums 和一个整数目标值 target ,请你在该数组中找出 和为目标值 target 的那两个整数,并返回它们的数组下标。 示例1: 输入:nums [2,7,11,15], target 9 输出:[0,1] 解释&…

【算法每日一练]-图论(lca) 最近公共祖先LCA,货车运输

目录 P3379:最近公共祖先LCA 思路: 货车运输 P3379:最近公共祖先LCA 思路: 首先进行的预处理,将所有点的深度和p数组求出来 设置:p[i][j]存的从i向上走2的j次方那么长的路径到的父节点 更深的点走到和…

PostgreSQL入门到实战-第二十二弹

PostgreSQL入门到实战 PostgreSQL中表连接操作(六)官网地址PostgreSQL概述PostgreSQL中self-join命令理论PostgreSQL中self-join命令实战更新计划 PostgreSQL中表连接操作(六) 使用PostgreSQL自联接技术来比较同一表中的行 官网地址 声明: 由于操作系统, 版本更新等原因, 文…

MySQL -- MySQL Connection C中的API介绍

MySQL – MySQL Connection C中的API介绍 文章目录 MySQL -- MySQL Connection C中的API介绍一、接口介绍1.初始化mysql_init()2. 链接数据库mysql_real_connect3.下发mysql命令mysql_query4.获取执行结果mysql_store_result5.获取结果行数和列数6.获取列名mysql_fetch_fields7…

0412备战蓝桥杯,图论复习

1.朴素dijkstra #include<algorithm> #include<iostream> #include<cstring> #include<queue> #include<cmath>using namespace std; const int N 510; int n,m; int g[N][N],dist[N]; bool st[N];int dij(){memset(dist,0x3f,sizeof dist);di…

内存函数memcpy、mommove、memset、memcmp

1、memcpy函数 描述&#xff1a; C 库函数 void *memcpy(void *str1, const void *str2, size_t n) 从存储区 str2 复制 n 个字节到存储区 str1。 声明&#xff1a; void *memcpy(void *str1, const void *str2, size_t n)参数&#xff1a; str1 -- 指向用于存储复制内容的目标…

【Redis实战避坑指南】深入剖析缓存雪崩、缓存穿透与缓存击穿:理解原理,规避风险

Redis作为高性能的键值存储系统&#xff0c;因其出色的读写性能和内存数据结构&#xff0c;被广泛应用于缓存场景。然而&#xff0c;在实际使用过程中&#xff0c;如果不妥善处理&#xff0c;可能会遭遇缓存雪崩、缓存穿透与缓存击穿等现象&#xff0c;严重影响系统的稳定性和性…

【电控笔记0】稳定度判断

简要概括 现控:原理虚轴,稳定度越高 自控:相位裕度PM 增益裕度GM 开环传函 不稳定条件判断

期望阻抗(Zd/s或Yd*s)的nyquist、bode与rlocus

在机器人控制领域中&#xff0c;针对具体的阻抗参数特性&#xff08;如质量、阻尼和刚度&#xff09;&#xff0c;Nyquist图、Bode图和根轨迹&#xff08;rlocus&#xff09;可以提供深入的分析和设计工具。 Nyquist图&#xff1a; 应用于阻抗参数&#xff1a;在机器人控制中&…

股票战法课程之交易系统

文章目录 1. 为什么要建立自己的交易系统2. 一个朋友的交易体系分享2.1 开仓原则2.2 计算盈亏比2.3 第三原则&#xff1a;资金管理原则2.4 持股原则2.5 技术指标 3. 作者本人的交易系统 1. 为什么要建立自己的交易系统 有稳定的交易系统&#xff0c;会让人很清晰的 知道什么样…

docker pull镜像的时候指定arm平台

指定arm平台 x86平台下载arm平台的镜像包 以mysql镜像为例 docker pull --platform linux/arm64 mysqldocker images查看镜像信息 要查看Docker镜像的信息&#xff0c;可以使用docker inspect命令。这个命令会返回镜像的详细信息&#xff0c;包括其元数据和配置。 docker i…

Nginx反向代理到访问者机器上(后端调试)

一、起因 因一名后端开发&#xff0c;不想使用postman等工具进行接口调试&#xff0c;因为web系统需要经过N多步骤的前置动作&#xff0c;不能保证参数的有效性&#xff0c;因此&#xff0c;需要直接点击web系统&#xff0c;触发本地后端代码。 但是&#xff0c;总不可能动不动…

Fast-lio2运行时如何显示轨迹线

修改对应设备的.yaml文件&#xff0c;以velodyne为例&#xff1a; 将 path_en参数改为true即可&#xff0c;运行其他设备&#xff0c;修改对应的参数

四、SpringBoot3 整合 Druid 数据源

本章概要 创建程序引入依赖启动类配置文件编写编写 Controller启动测试问题解决 4.1 创建程序 4.2 引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://ww…

【C++ STL序列容器】deque 双端队列

文章目录 【 1. 基本原理 】【 1. deque 的创建 】1.1 创建一个空的 deque1.2 创建一个 n 个默认值的 deque1.3 创建一个 n 个指定值的 deque1.4 通过一个 deque 初始化另一个 deque1.5 通过基础容器来初始化 queue 容器适配器 【 3. deque 支持的成员函数 】 【 1. 基本原理 】…

不惑之年,反思我如何成为一个程序员

不惑之年&#xff0c;反思我如何成为一个程序员 文章目录 不惑之年&#xff0c;反思我如何成为一个程序员01/偶然掉入码河02/现实撕碎理想03/发展选择方向04/时代成就向往05/幸运装饰未来 在这个充满生机与希望的季节&#xff0c;博主有幸收到一家国企邀约面试&#xff0c;并顺…

通俗易懂HTTP和HTTPS区别

HTTP&#xff1a;超文本传输协议&#xff0c;它是使用一种明文的方式发送我们的内容&#xff0c;没有任何的加密&#xff0c;例如我们要在网页上输入账号密码&#xff0c;如果使用HTTP协议&#xff0c;账号密码就可能会被暴露&#xff0c;默认端口是80. HTTPS&#xff1a;是HT…

护眼台灯品牌哪个好?2024五大护眼台灯排行榜分享

​护眼台灯作为家庭中常见的照明工具&#xff0c;其存在几乎成为了现代生活的标配。家长们往往会为孩子购置一台&#xff0c;供学习和阅读使用&#xff1b;同时&#xff0c;它也是学生和办公人员在夜晚工作学习的必备之物。然而&#xff0c;市面上的一些普通台灯可能存在着种种…

Springboot使用教程

二、配置文件 SpringBoot使用一个全局的配置文件&#xff0c;配置文件名是固定的&#xff1b; •application.properties •application.yml 1.配置文件的作用&#xff1a; 修改SpringBoot自动配置的默认值&#xff1b;SpringBoot在底层都给我们自动配置好&#xff1b; Y…