Java设计模式之命令模式
目录
定义
结构
案例
优点
缺点
使用场景
JDK源码解析
Thread中start与run方法的区别
定义
将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储、传递、调用、增加与管理。
结构
命令模式包含以下主要角色:
- 抽象命令类角色: 定义命令的接口,声明执行的方法。
- 具体命令角色:具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
- 实现者/接收者角色: 接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。
- 调用者/请求者角色: 要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。
案例
抽象命令类
public interface Command {void execute();
}
具体命令类
public class OrderCommand implements Command {//接收者对象private SeniorChef receiver;private Order order;public OrderCommand(SeniorChef receiver, Order order) {this.receiver = receiver;this.order = order;}@Overridepublic void execute() {System.out.println("去执行"+order.getTableNum()+"桌子的订单");Set<String> ordersName = this.order.getOrder().keySet();for (String name : ordersName) {receiver.makeFood(name,order.getOrder().get(name));}}
}
接收类
public class SeniorChef {public void makeFood(String name,Integer number){System.out.println("厨师提供了:"+name+number+"份");}
}//订单类。作为信息传递的媒介
public class Order {//订单号private String tableNum;//存储菜名与数量private Map<String,Integer> order = new HashMap<>();public Order(String tableNum) {this.tableNum = tableNum;}public String getTableNum() {return tableNum;}public void setTableNum(String tableNum) {this.tableNum = tableNum;}public Map<String, Integer> getOrder() {return order;}public void setOrder(String name, Integer number) {order.put(name,number);}
}
调用类
public class Waiter {private List<Command> commands;//可以存储多个命令public Waiter() {commands = new ArrayList<>();}public void setCommand(Command command) {commands.add(command);}public void call(){System.out.println("服务生发出命令给厨师");for (int i = 0; i < commands.size(); i++) {commands.get(i).execute();}}
}
测试
public class Client {public static void main(String[] args) {SeniorChef receive = new SeniorChef();Order order = new Order("1号");order.setOrder("食物A",2);Command command = new OrderCommand(receive, order);Waiter waiter = new Waiter();waiter.setCommand(command);waiter.call();}
}
服务生发出命令给厨师
去执行1号桌子的订单
厨师提供了:食物A2份
主要实现了请求者与接收者之间的解耦。
优点
- 降低系统的耦合度。命令模式能将调用操作的对象与实现该操作的对象解耦。
- 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
- 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
- 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。
缺点
- 使用命令模式可能会导致某些系统有过多的具体命令类。但不至于类爆炸
- 系统结构更加复杂。
使用场景
- 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。
- 系统需要在不同的时间指定请求、将请求排队和执行请求。
- 系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。
JDK源码解析
Runable是一个典型命令模式,Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法(Thread重写了Runnable中的run方法应该也是执行方法。)

这是抽象命令类,只有一个抽象方法run()。

这是调用者类,里面包含了Runable类的对象。
public synchronized void start() {/*** This method is not invoked for the main method thread or "system"* group threads created/set up by the VM. Any new functionality added* to this method in the future may have to also be added to the VM.** A zero status value corresponds to state "NEW".*/if (threadStatus != 0)throw new IllegalThreadStateException();/* Notify the group that this thread is about to be started* so that it can be added to the group's list of threads* and the group's unstarted count can be decremented. */group.add(this);boolean started = false;try {start0();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}}
在调用方法中会调用一个native方法start0(),调用系统方法,开启一个线程。而接收者是对程序员开放的,可以自己定义接收者。

//具体命令类
public class TurnOffThread implements Runnable {//接收者private Receive receive;public TurnOffThread(Receive receive) {this.receive = receive;}@Overridepublic void run() {receive.turnOff();}
}
//接收者类由程序员自己定义
public class Receive {public void turnOff(){System.out.println("关闭线程");}
}
public class Client {public static void main(String[] args) {//接收者,自定义的Receive receive = new Receive();//具体命令角色,指定了接收者用于调用接收者的方法Runnable runnable = new TurnOffThread(receive);//调用者//这里Thread指定了Runnable对象,那么在Thread初始化时,就会将该对象存储在创建出来的Thread对象中,Thread中的run方法调用的就是指定的Runnable对象Thread thread = new Thread(runnable);System.out.println(thread.getName()+"开始执行");thread.start();thread.run();}
}
Thread-0开始执行
关闭线程
关闭线程
Thread中start与run方法的区别
如果在客户端直接使用run方法相当于是在当前线程执行方法,并不会创建一个新的线程去执行。而start方法是创建出一个新的线程后,在新线程中去执行run方法。
源码中,start方法中调用了系统方法start0方法,作用是创建一个线程。而run方法是通过JVM自动调用。
相关文章:
Java设计模式之命令模式
目录 定义 结构 案例 优点 缺点 使用场景 JDK源码解析 Thread中start与run方法的区别 定义 将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行存储、传递、调用、增…...
记录一段帮朋友写的代码,使用牛顿-拉夫逊方法解方程
要求 已知公式: t G A B F r B r 2 2 F A 2 B G A F ln ( r − A ) C o n s t t\frac{GAB}{F}r\frac{Br^2}{2F}\frac{A^2BGA}{F}\ln (r-A)Const tFGABr2FBr2FA2BGAln(r−A)Const 其中 t 的值为0-1000,每间隔25取一次值A2.12941E-10B0.…...
滑动窗口限流算法实现一
固定算法 原理:固定算法是将时间线分隔成固定大小的时间窗口,每个窗口都会有个计数器,用来记录窗口时间范围内的请求总数,如果窗口的请求总数达到最大限定值,会认定流量超限。比如将窗口大小设为1分钟,每分…...
简单明了!网关Gateway路由配置filters实现路径重写及对应正则表达式的解析
问题背景: 前端需要发送一个这样的请求,但出现404 首先解析请求的变化: http://www.51xuecheng.cn/api/checkcode/pic 1.请求先打在nginx,www.51xuecheng.cn/api/checkcode/pic部分匹配到了之后会转发给网关进行处理变成localho…...
EMQX内置Web管理控制台-Dashboard
一、Dashboard概述 EMQX Dashboard官网文档:https://docs.emqx.com/zh/enterprise/v5.1/dashboard/introduction.html 1、简介 EMQX 为用户提供了一个功能强大的内置管理控制台,即 EMQX Dashboard。通过这个控制台的 Web 界面,用户可以轻松监…...
计算机网络重点概念整理-第四章 网络层【期末复习|考研复习】
计算机网络复习系列文章传送门: 第一章 计算机网络概述 第二章 物理层 第三章 数据链路层 第四章 网络层 第五章 传输层 第六章 应用层 第七章 网络安全 计算机网络整理-简称&缩写 文章目录 前言四、网络层4.1 网络层功能4.1.1 电路交换、报文交换与分组交换4.1…...
数组转树形数据
const nodes [{ id: 3, name: 节点C, pid: 1 },{ id: 6, name: 节点F, pid: 3 },{ id: 0, name: root, pid: null },{ id: 1, name: 节点A, pid: 0 },{ id: 8, name: 节点H, pid: 4 },{ id: 4, name: 节点D, pid: 1 },{ id: 2, name: 节点B, pid: 0 },{ id: 5, name: 节点E, p…...
react动态插入样式
在开发组件过程中,偶尔需要动态的插入css,比如在在iframe中渲染组件后,iframe中是没有样式的,所以需要手动插入样式。 插入样式 通常是在useLayoutEffect中动态创建style标签 useLayoutEffect(() > {if (!ref.current) {cons…...
OkHttp网络框架深入理解-SSL握手与加密
OkHttp简介 由Square公司贡献的一个处理网络请求的开源项目,是目前Android使用最广泛的网络框架。从Android4.4开始HttpURLConnection的底层实现采用的是OkHttp。 特点: 支持HTTP/2并允许对同一主机的所有请求共享一个套接字通过连接池,减少了请求延迟…...
Mac 安装使用NPM及常用命令
环境: Mac 工具: NPM 可通过官网查询一些模块相关 NPM Doc 通过官网文档了解更多的关于NPM的使用 安装 NPM是Node.js的包管理工具,可用于解决 Node.js在代码部署上的问题。 新版本的Node.js已经集成了NPM, 因此可通过下载 Nod…...
利用 JSqlParser 防止 SQL 注入
高手文章《jsqlparser:实现基于SQL语法分析的SQL注入攻击检查》介绍了利用 JSqlParser 防止 SQL 注入,写得很好,只不过有两个问题,代码比较复杂,我于是作了简化,只有两个类;其次检测比较严格,连…...
10.27~10.29数电第三次实验分析与问题
实验要求 分析 寄存器 D触发器有两个输出口,一个输入口,一个时钟信号,一个复位信号 同步异步就是说复位信号在不在always里 给它加一个load就成了一位寄存器, 寄存器堆 8个8位的寄存器堆,每个寄存器都有两读一写…...
【软考】14.3 设计模式
《设计模式》 有下划线:类模式 / 对象模式无下划线:对象模式 创建型 设计模式 创建对象 构建器(Builder):类和构造分离抽象工厂(Abstract Factory):抽象接口工厂(Factor…...
Mac docker+vscode
mac 使用docker vs code 通过vscode 可以使用docker容器的环境。 可以在容器安装gdb, 直接调试代码。 创建容易时候可以指定目录和容易目录可以共享文件。...
LLVM学习笔记(58)
4.4. 目标机器对象 在main()函数的350行,TimeCompilations默认为1,可以通过隐藏的选项“-time-compilations”来指定它的值,它的作用是重复进行指定次数的编译,以得到更好的编译用时数据。而在这个循环中调用的compileModule()&a…...
C语言 每日一题 PTA 10.30 day8
1.高空坠球 皮球从某给定高度自由落下,触地后反弹到原高度的一半,再落下,再反弹,……,如此反复。问皮球在第n次落地时,在空中一共经过多少距离?第n次反弹的高度是多少? 输入格式 : …...
nacos在linux中的安装、集群的配置、mysql生产配置
1.下载和安装 官方下载地址:https://github.com/alibaba/nacos/releases,根据自己需要的本版去下载就行 下载的是 .tar.gz 后缀的文件是linux版本的 使用tar命令解压,完成之后是一个nacos的文件夹 和windows下的文件夹目录是一样的 要启…...
OpenAI 组建安全 AGI 新团队!应对AI“潘多拉魔盒”
夕小瑶科技说 原创 作者 | 小戏 一旦谈及未来 AI,除了天马行空的科幻畅想,不可避免的也有未来 AI 时代的末日预言。从 AI 武器化到 AI 欺骗,从邪恶 AI 到 AI 掌权,人工智能,尤其是通用人工智能的风险始终都清清楚楚的…...
上网行为管理软件有哪些丨功能图文超详细介绍
很多人都在后台问,上网行为管理软件到底是什么,有什么作用,今天就重点给大家讲解一下: 是什么 上网行为管理软件可以帮助企业规范员工的上网行为,提高办公效率,减少潜在威胁。 有哪些 在市面上ÿ…...
DVWA-SQL Injection SQL注入
概念 SQL注入,是指将特殊构造的恶意SQL语句插入Web表单的输入或页面请求的查询字符串中,从而欺骗后端Web服务器以执行该恶意SQL语句。 成功的 SQL 注入漏洞可以从数据库中读取敏感数据、修改数据库数据(插入/更新/删除)、对数据…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
