初识设计模式 - 命令模式

news/2024/11/13 4:33:43/

简介

命令设计模式(Command Design Pattern)可以将请求发送者和接收者完全解耦。发送者和接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。

其定义是,将请求(命令)封装成一个对象,从而可用不同的请求对客户进行参数化(将不同请求依赖注入到其他对象),并且能够支持请求(命令)的排队执行、记录日志、撤销等(附加控制)功能。

典型实现

首先,定义一个抽象命令 Command 接口,通常仅声明一个执行命令的方法,其代码示例如下:

 
public interface Command {
// 业务处理方法
void execute();
}

具体命令会实现各种类型的请求,其自身并不完成工作,而是将调用委派给一个业务逻辑对象,其代码示例如下:

 
public class ConcreteCommand implements Command {
// 维持一个对请求者对象的引用
private final Receiver receiver;
public ConcreteCommand(Receiver receiver) {
this.receiver = receiver;
}
// 调用请求接收者的业务处理方法
public void execute() {
this.receiver.action();
}
}

接收者是真正命令执行的对象,是客户端直接操作的对象,其代码示例如下:

 
public class Receiver {
public void action() {
// 具体操作
}
}

最后,需要定义的是调用者 Invoker 类,其作用是负责对请求进行初始化,其代码示例如下:

 
public class Invoker {
private final List<Command> commandList;
public Invoker() {
this.commandList = new ArrayList<>();
}
public Invoker(Command command) {
this();
this.commandList.add(command);
}
// 添加命令
public void pushCommand(Command command) {
this.commandList.add(command);
}
// 执行命令
public void executeAll() {
for (Command command : commandList) {
command.execute();
}
commandList.clear();
}
}

对于客户端而言,需要知道自己需要操作的接收者对象是什么、可以执行的命令有哪些、通过调用者如何去执行这些命令。

如下是客户端使用命令模式的代码示例:

 
public class CommandDemo {
public static void main(String[] args) {
// 操作的接收者对象是什么
Receiver receiver = new Receiver();
// 可以执行的命令有哪些
Command command = new ConcreteCommand(receiver);
// 通过调用者如何去执行这些命令
Invoker invoker = new Invoker(command);
invoker.executeAll();
}
}

总结

优点

命令模式的主要优点如下:

  • 降低请求者和接收者的耦合度
  • 新的命令可以很方便地加入到系统中
  • 可以比较容易地设计一个命令队列或者宏命令(组合命令)
  • 为请求的撤销和恢复操作提供了一种设计和实现方案

缺点

命令模式的主要缺点如下:

  • 可能会导致系统中有过多的具体命令类

适用场景

命令模式的适用场景如下:

  • 系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互
  • 系统需要在不同的时间指定请求、将请求排队和执行请求
  • 系统需要支持命令的撤销操作和恢复操作
  • 系统需要将一组操作组合在一起形成宏命令

源码

在 JDK 中,Runnable 接口就类似于命令模式的命令接口。

只要实现了 Runnable 接口的类都被认为是一个线程类,相当于命令模式中具体命令类的角色。而实现了 Runnable 接口的 Thread 类既可以作为具体命令类,也可以作为调用者。

如下是客户端使用 Runnable 和 Thread 的代码示例:

 
public class ThreadDemo {
public static void main(String[] args) {
Runnable command = new Runnable() {
@Override
public void run() {
System.out.println("command 线程执行");
}
};
Thread thread = new Thread(command);
// command 线程执行
thread.start();
}
}

http://www.ppmy.cn/news/40489.html

相关文章

常用异常检测模型的应用

常用异常检测模型的应用 描述 异常数据检测不仅仅可以帮助我们提高数据质量&#xff0c;同时在一些实际业务中&#xff0c;异常数据往往包含有价值的信息&#xff0c;如异常交易、网络攻击、工业品缺陷等&#xff0c;因此异常检测也是数据挖掘的重要手段。常用的异常检测模型…

spring 概述

正常的三层架构违背了OCP开闭原则&#xff0c;DIP依赖倒置原则 OCP核心原则为:只要你在扩展系统功能的时候&#xff0c;没有修改过以前写好的代码&#xff0c;就负责OCP原则&#xff0c;反之&#xff0c;如果在扩展系统功能的时候&#xff0c;修改了&#xff0c;则这个设计是失…

Java 微服务架构

Java 微服务架构是一个分布式系统&#xff0c;由多个小型、松耦合的服务组成&#xff0c;每个服务运行在独立的进程中&#xff0c;并通过轻量级的协议进行通信。微服务架构的优势在于提高了应用的可伸缩性、灵活性和可维护性&#xff0c;同时还可以使团队更容易协作开发。 下面…

pixel显示网络无法连接解决

pixel显示网络无法连接解决 可以上网&#xff0c;但显示不可上网 输入以下三行命令即可 adb shell settings put global captive_portal_server www.google.cn adb shell settings put global captive_portal_https_url https://www.google.cn/generate_204 adb shell setting…

使用模板窗口生成测试数据

1. 准备工作 需要的环境 Oralce、MySQL、PG等主流数据库HHDBCS7.6及以上版本 测试步骤 建立两张表带有主外键关系使用模板窗口生成数据&#xff0c;主键表生成100条&#xff0c;外键表生成10000条校验数据生成情况 2. 建立两张表带有主外键关系 主键表 create table dept…

java 有继承关系的类的静态变量和非静态变量以及代码块的初始化顺序

类B继承A 在main函数中new一个B类对象 1.父类 静态变量初始化和静态代码先执行 2.再执行子类静态变量初始化和静态代码块 3.再进入B类构造器&#xff0c;以下图顺序进行执行 B中super进入A类构造器&#xff0c;同样是以这个顺序进行执行&#xff0c;A的父类是Object&#x…

本地安装WSL的发行版后,导出到另一台计算机安装的办法

一、步骤 1、首先你要在你的计算机上安装成功了WSL子系统&#xff0c;然后才能导出对应版本的tar文件&#xff0c;复制到另一台计算机中进行安装 2、例如我的电脑安装了Ubuntu 20.04.5这个版本&#xff0c;如图&#xff1a; 3、同时可以在命令提示符中只用命令wsl --list --ve…

脂肪肝 肾结石 怎么得来的

脂肪肝怎么得来的1.脂肪肝2.肾结石是如何产生的&#xff1f;1.脂肪肝 是由于肝细胞内脂肪堆积过多引起的慢性疾病&#xff0c;引起脂肪肝的因素有多种&#xff0c;由于常常没有自觉症状&#xff0c;往往不易引起人们的重视。常见原因有以下几种&#xff1a; 第一、过量饮酒&a…