设计模式之 命令模式
命令模式(Command Pattern)是行为型设计模式之一,它将请求(或命令)封装成一个对象,从而使用户能够将请求发送者与请求接收者解耦。通过命令模式,调用操作的对象与执行操作的对象不直接关联,命令对象作为一个中介,传递请求和执行的责任,使得用户可以通过简单的调用接口来执行复杂的行为。
一、命令模式的基本概念
命令模式的核心思想是将请求封装为一个对象,通常这个对象包含了执行某个特定操作的必要信息和执行的逻辑。当请求被调用时,该命令对象会通知相应的执行者对象执行特定的操作。通过这种方式,命令的调用者和执行者之间无需直接交互,符合松耦合的设计原则。
1. 主要组成部分
命令模式通常包括以下几个关键角色:
-
Command(命令接口):声明了执行命令的接口,通常包含一个
execute()方法。 -
ConcreteCommand(具体命令类):实现了命令接口,封装了与特定请求相关的动作,并将请求转发给接收者对象。
-
Receiver(接收者类):执行与请求相关的具体操作。它知道如何执行与请求相关的操作。
-
Invoker(调用者类):请求命令的发送者,它持有一个命令对象,并在适当的时候调用该命令对象的
execute()方法。 -
Client(客户端):客户端创建一个具体的命令对象,并设置其接收者。客户端通常还会将该命令对象传递给调用者。
2. 工作原理
命令模式的工作原理是,当客户端希望执行某个操作时,它创建一个命令对象(通常是ConcreteCommand的实例),并将该对象交给调用者。调用者在适当的时候调用execute()方法,命令对象将请求委托给接收者进行实际的操作。由于所有的请求都通过命令对象封装并传递,调用者与接收者完全解耦。
二、命令模式的代码示例
-
命令接口
public interface Command {void execute(); } -
具体命令类
public class OrderCommand implements Command{private Chef chef;private Order order;public OrderCommand(Chef chef, Order order) {this.chef = chef;this.order = order;}@Overridepublic void execute() {System.out.println(order.getDiningTable()+"桌的餐");Set<String> foodNames = order.getFoodDesc().keySet();for (String foodName : foodNames) {chef.makeFood(order.getFoodDesc().get(foodName), foodName);}} } -
厨师
public class Chef {public void makeFood(int number, String foodName){System.out.println("正在制作"+number+"份"+foodName);} } -
调用者类
public class Waitor {private List<Command> commands = new ArrayList<>();public void setCommand(Command command){commands.add(command);}public void OrderUp(){commands.forEach(command -> {command.execute();});} } -
订单实体类
public class Order {private int diningTable;Map<String,Integer> foodDesc = new HashMap<>();public int getDiningTable() {return diningTable;}public void setDiningTable(int diningTable) {this.diningTable = diningTable;}public Map<String, Integer> getFoodDesc() {return foodDesc;}public void setFoodDesc(String name,Integer num) {foodDesc.put(name, num);} } -
客户端代码
public class Client {public static void main(String[] args) {Order order = new Order();order.setDiningTable(1);order.setFoodDesc("西红柿炒蛋", 2);order.setFoodDesc("拉面", 2);Command command = new OrderCommand(new Chef(), order);command.execute();} } -
输出结果

三、命令模式的优缺点
优点:
- 解耦请求者与执行者:调用者(Invoker)不需要知道具体的执行操作,只需要通过命令接口进行调用,避免了直接依赖具体的执行类。请求者和执行者之间的耦合度降低,系统更灵活。
- 支持命令的撤销与恢复:命令模式可以很方便地实现命令的撤销(Undo)和恢复(Redo)功能。通过保存历史命令,可以在需要时撤销之前的操作。
- 增加新的命令:添加新的命令非常简单,只需要定义一个新的命令类并实现
Command接口,不需要修改现有的类或调用者,符合开闭原则。 - 组合命令:多个命令可以组合成一个“复合命令”,通过调用一个复合命令来依次执行多个操作,方便管理多个命令的执行。
缺点:
- 类的数量增加:命令模式会导致系统中增加很多命令类,特别是在命令种类多的情况下,可能会使系统变得较为复杂。
- 可能不必要的复杂度:对于一些简单的应用,命令模式可能会引入不必要的复杂度。在这些情况下,直接在客户端调用相关方法可能更加简洁。
- 客户端需要了解命令对象:虽然命令模式解耦了请求者与执行者,但客户端需要了解如何配置和使用命令对象,这可能增加一些学习和使用的成本。
四、命令模式的应用场景
命令模式特别适用于以下几种场景:
-
GUI(图形用户界面)按钮操作:
在GUI应用中,用户点击按钮通常会触发一些行为,命令模式非常适合将按钮的操作封装为命令对象,解耦按钮与具体操作的实现。通过命令对象,可以将按钮的功能独立出来,方便修改和扩展。 -
事务管理:
对于需要管理多个操作的系统,命令模式可以用来记录每个操作(命令),并且在需要时执行或撤销这些操作。比如在事务处理系统中,可以使用命令模式来实现事务的提交、回滚操作。 -
宏命令:
如果某个操作需要执行一系列操作,可以通过将多个命令对象组合成一个复合命令(Macro Command),从而一次性执行一组操作。 -
日志系统:
在一些系统中,操作可能需要被记录(例如,用户在系统中执行了某个动作)。可以将每个操作封装成命令对象,并在执行时记录这些操作,甚至可以在以后重新执行。 -
远程操作系统:
在需要远程控制设备的场景中,命令模式可以帮助将操作封装成命令对象,通过网络发送命令对象,从而远程执行设备操作。
相关文章:
设计模式之 命令模式
命令模式(Command Pattern)是行为型设计模式之一,它将请求(或命令)封装成一个对象,从而使用户能够将请求发送者与请求接收者解耦。通过命令模式,调用操作的对象与执行操作的对象不直接关联&…...
24.11.23 Ajax
1动态网页技术与静态网页技术对比: 静态网页: 如果数据库中有用户列表 html中要显示 如果用户列表数据变化 html要改代码才能显示完整数据 (不能使用动态数据 ) 动态网页: servlet可以通过代码 以输出流显示数据 当数据库数据改变时 不需要改代码 2.为了解决html不能使用动…...
Sickos1.1 详细靶机思路 实操笔记
Sickos1.1 详细靶机思路 实操笔记 免责声明 本博客提供的所有信息仅供学习和研究目的,旨在提高读者的网络安全意识和技术能力。请在合法合规的前提下使用本文中提供的任何技术、方法或工具。如果您选择使用本博客中的任何信息进行非法活动,您将独自承担…...
rk3568-linux-5.10.160移植rtl8822cs wifi 模块纪要
rk3568-linux-5.10.160移植rtl8822cs wifi 模块纪要 1、将驱动添加到 kernel/drivers/net/wireless/rockchip_wlan/ 或者 kernel/drivers/net/wireless/realtek/rtlwifi/ 2、修改该目录下的makefile、kconfig 3、修改rtl8822cs/os_dep/linux/os_intfs.c,添加 MO…...
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
一、编码问题 在计算机编程中,流(Stream)是一种抽象的概念,用于表示数据的输入或输出。根据处理数据的不同方式,流可以分为字节流(Byte Stream)和字符流(Character Stream࿰…...
学习electron
一、开发环境 1、先行安装 node.js 和 npm 2、检查 Node.js 是否正确安装,请在您的终端输入以下命令:检测安装的版本 node -v npm -v 注意 因为 Electron 将 Node.js 嵌入到其二进制文件中,你应用运行时的 Node.js 版本与你系统中运…...
《C++智能合约与区块链底层交互全解析:构建坚实的去中心化应用桥梁》
在区块链技术的广阔天地里,C智能合约扮演着极为关键的角色,而其与区块链底层的交互则是实现各种去中心化应用功能的核心环节。深入理解并掌握这种交互机制,对于区块链开发者来说至关重要,它犹如一座桥梁,将智能合约的业…...
MySQL:事务
什么是事务 事务就是把SQL语句打包成一个整体,在这组SQL执行的时候,要么同时成功,要么同时失败。 事务的ACID特性 事务的ACID特性指的是 Atomicity (原⼦性), Consistency (⼀致性), Isolation (隔离 性)和 Durabi…...
Linux——进程间通信之管道
进程间通信之管道 文章目录 进程间通信之管道1. 进程间通信1.1 为什么要进行进程间的通信1.2 如何进行进程间的通信1.3 进程间通信的方式 2. 管道2.1 匿名管道2.1.1 系统调用pipe()2.1.2 使用匿名管道进行通信2.1.1 匿名管道四种情况2.1.2 匿名管道的五大特性2.1.3 进程池 2.2 …...
java-排序算法汇总
排序算法: 冒泡排序(Bubble Sort) 选择排序(Selection Sort) 插入排序(Insertion Sort) 快速排序(Quick Sort) 归并排序(Merge Sort) 堆排序&…...
Vscode进行Java开发环境搭建
Vscode进行Java开发环境搭建 搭建Java开发环境(Windows)1.Jdk安装2.VsCode安装3.Java插件4.安装 Spring 插件5.安装 Mybatis 插件5.安装Maven环境6.Jrebel插件7.IntelliJ IDEA Keybindings8. 收尾 VS Code(Visual Studio Code)是由微软开发的一款免费、开…...
算法学习笔记(五):二叉树一遍历、DFS
一.遍历二叉树 二叉树TreeNode类 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, Tree…...
#Verilog HDL# Verilog中的generate用法集锦
生成块允许复制模块实例或有条件地实例化任何模块。它提供了基于Verilog参数构建设计的能力。当相同的操作或模块实例需要重复多次,或者当某些代码需要根据给定的Verilog参数有条件地包含时,这些语句特别方便。 生成块不能包含端口、参数、specparam声明或指定块。但是,允许…...
简述C++map容器
pair键值对 std::pair在很多关联容器(如std::map、std::multimap、std::set、std:multiset等)中被广泛应用。以std::map为例,std::map是一个键值对的容器,其中每个元素都是一个std::pair,键用于唯一标识元…...
Vue 学习随笔系列十七 -- 表格样式修改
表格样式修改 文章目录 表格样式修改一、表格背景颜色修改1、方法一2、方法二 二、多级表头颜色修改 一、表格背景颜色修改 1、方法一 表格外套一个 div ,修改div的背景色,并将表格背景色设置为透明 参考代码: <template><div cl…...
08 —— Webpack打包图片
【资源模块 | webpack 中文文档 | webpack中文文档 | webpack中文网】https://www.webpackjs.com/guides/asset-modules/?sid_for_share99125_3 Webpack打包图片以8KB为临界值判断 大于8KB的文件:发送一个单独的文件并导出URL地址 小于8KB的文件:导出一…...
01.Django快速入门
一、Django 快速入门 使用最新版本 Django4.2LTS 版本,3 年内不需要更换版本由浅入深讲解,浅显易懂课程大纲全面包含 Django 框架知识点,内容丰富全面细致知识点结合项目实战实现全栈项目应用 Django 官网(文档): https://docs.djangoproject.com/zh-h…...
【大数据学习 | Spark-Core】spark-shell开发
spark的代码分为两种 本地代码在driver端直接解析执行没有后续 集群代码,会在driver端进行解析,然后让多个机器进行集群形式的执行计算 spark-shell --master spark://nn1:7077 --executor-cores 2 --executor-memory 2G sc.textFile("/home/ha…...
Modern Effective C++ Item 14 如果函数不抛出异常请使用noexcept
C11 noexcept关键字用于指定函数不会抛出异常,有助于提高程序的异常安全性,还能够使编译器生成更加高效的代码。 noexcept 是函数接口的一部分 函数是否声明为 noexcept 是接口设计的一部分,客户端代码可能会依赖这一点。如果一个函数被声明…...
cudatoolkit安装(nvcc -V错误版本解决)
CudaToolKit安装(nvcc) cudatoolkit 是 CUDA 开发工具包(CUDA Toolkit) 的核心部分,包含了一系列用于开发和运行 CUDA 应用程序的软件组件。nvcc 是 NVIDIA CUDA 编译器驱动,用于将 CUDA C/C 代码编译成可…...
手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...
游戏开发中常见的战斗数值英文缩写对照表
游戏开发中常见的战斗数值英文缩写对照表 基础属性(Basic Attributes) 缩写英文全称中文释义常见使用场景HPHit Points / Health Points生命值角色生存状态MPMana Points / Magic Points魔法值技能释放资源SPStamina Points体力值动作消耗资源APAction…...
