【设计模式】【行为型模式(Behavioral Patterns)】之命令模式(Command Pattern)

devtools/2024/11/27 20:28:10/

1. 设计模式原理说明

命令模式(Command Pattern) 是一种行为设计模式,它将请求封装成对象,从而使你可以用不同的请求对客户进行参数化、队列请求或将请求日志化,同时支持可撤销的操作。通过这种方式,可以将请求发送者与接收者解耦,使得两者之间不再直接联系,而是通过命令对象进行交互。

主要角色
  1. Command(命令接口):声明执行操作的接口。
  2. ConcreteCommand(具体命令):将接收者对象与动作绑定,调用接收者相应的操作,实现Command接口。
  3. Receiver(接收者):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
  4. Invoker(调用者):要求该命令执行这个请求,它依赖于Command。
  5. Client(客户端):创建具体的命令对象,并设置其接收者。

2. UML 类图及解释

UML 类图
+-----------------+                +-----------------+
|   Command       |                |    Receiver     |
|-----------------|                |-----------------|
| - execute()     |                | - action()      |
+-----------------+                +-----------------+^                               ^|                               ||                               |v                               v
+-----------------+                +-----------------+
| ConcreteCommand |                |   ConcreteReceiver|
|-----------------|                |-----------------|
| - receiver: Receiver |            | - action()      |
| - execute()      |                +-----------------+
+-----------------+                    ^||v
+-----------------+
|     Invoker     |
|-----------------|
| - command: Command |
| - setCommand(command: Command) |
| - executeCommand() |
+-----------------+
类图解释
  • Command:定义了执行操作的接口。
  • ConcreteCommand:实现了Command接口,将接收者对象与动作绑定。
  • Receiver:执行具体的操作,可以是任何类。
  • Invoker:负责调用命令对象的execute方法,但不关心具体执行什么操作。
  • Client:创建命令对象并设置接收者,然后将命令对象传递给调用者。

3. 代码案例及逻辑详解

Java 代码案例
// 命令接口
interface Command {void execute();
}// 接收者
class Receiver {public void action() {System.out.println("Executing action");}
}// 具体命令
class ConcreteCommand implements Command {private Receiver receiver;public ConcreteCommand(Receiver receiver) {this.receiver = receiver;}@Overridepublic void execute() {receiver.action();}
}// 调用者
class Invoker {private Command command;public void setCommand(Command command) {this.command = command;}public void executeCommand() {if (command != null) {command.execute();}}
}// 客户端
public class Client {public static void main(String[] args) {Receiver receiver = new Receiver();Command command = new ConcreteCommand(receiver);Invoker invoker = new Invoker();invoker.setCommand(command);invoker.executeCommand();}
}
C++ 代码案例
#include <iostream>// 命令接口
class Command {
public:virtual ~Command() {}virtual void execute() = 0;
};// 接收者
class Receiver {
public:void action() {std::cout << "Executing action" << std::endl;}
};// 具体命令
class ConcreteCommand : public Command {
private:Receiver* receiver;
public:ConcreteCommand(Receiver* receiver) : receiver(receiver) {}void execute() override {receiver->action();}
};// 调用者
class Invoker {
private:Command* command;
public:void setCommand(Command* command) {this->command = command;}void executeCommand() {if (command != nullptr) {command->execute();}}
};// 客户端
int main() {Receiver receiver;Command* command = new ConcreteCommand(&receiver);Invoker invoker;invoker.setCommand(command);invoker.executeCommand();delete command;return 0;
}
Python 代码案例
# 命令接口
class Command:def execute(self):raise NotImplementedError# 接收者
class Receiver:def action(self):print("Executing action")# 具体命令
class ConcreteCommand(Command):def __init__(self, receiver):self.receiver = receiverdef execute(self):self.receiver.action()# 调用者
class Invoker:def __init__(self):self.command = Nonedef set_command(self, command):self.command = commanddef execute_command(self):if self.command:self.command.execute()# 客户端
if __name__ == "__main__":receiver = Receiver()command = ConcreteCommand(receiver)invoker = Invoker()invoker.set_command(command)invoker.execute_command()
Go 代码案例
package mainimport ("fmt"
)// 命令接口
type Command interface {execute()
}// 接收者
type Receiver struct{}func (r *Receiver) action() {fmt.Println("Executing action")
}// 具体命令
type ConcreteCommand struct {receiver *Receiver
}func (c *ConcreteCommand) execute() {c.receiver.action()
}// 调用者
type Invoker struct {command Command
}func (i *Invoker) setCommand(command Command) {i.command = command
}func (i *Invoker) executeCommand() {if i.command != nil {i.command.execute()}
}// 客户端
func main() {receiver := &Receiver{}command := &ConcreteCommand{receiver: receiver}invoker := &Invoker{}invoker.setCommand(command)invoker.executeCommand()
}

4. 总结

命令模式 是一种行为设计模式,它将请求封装成对象,从而使你可以用不同的请求对客户进行参数化、队列请求或将请求日志化,同时支持可撤销的操作。通过这种方式,可以将请求发送者与接收者解耦,使得两者之间不再直接联系,而是通过命令对象进行交互。

主要优点
  1. 解耦命令模式将请求的发送者和接收者解耦,使得两者之间不再直接联系。
  2. 扩展性:新增命令时,只需添加新的具体命令类,无需修改现有代码,符合开闭原则。
  3. 支持撤销操作:命令对象可以保存状态,从而支持撤销和重做操作。
  4. 支持队列请求:可以将命令对象放入队列中,实现异步处理。
主要缺点
  1. 增加系统复杂度:引入命令模式会增加系统的复杂度,因为需要额外的命令类和调用者类。
  2. 性能开销命令模式可能会带来一些性能开销,特别是在命令对象较多时。
适用场景
  • 当需要将请求排队或记录请求日志,或者支持可撤销操作时。
  • 当需要参数化对象来指定要执行的操作时。
  • 当需要在不同的时刻指定、排列和执行请求时。
  • 当需要将请求发送者与接收者解耦时。

http://www.ppmy.cn/devtools/137481.html

相关文章

svn-git下载

windows&#xff1a; svn 客户端&#xff1a;-------------- TortoiseSVN 安装 下载地址&#xff1a;https://tortoisesvn.net/downloads.html, 页面里有语言包补丁的下载链接。 目前最新版为 1.11.0 下载地址&#xff1a; https://osdn.net/projects/tortoisesvn/storage/1.…

kali安装及使用docker和docker-compose

安装docker及docker-compose&#xff1a; &#xff08;这里我之前安装过了&#xff0c;借用别人的教程来讲解&#xff09; 更新可用软件包&#xff1a; apt-get update 开始安装docker&#xff1a; apt install docker.io 如果有让确认的&#xff0c;输入 y 即可&#xff1a…

springMVC 全局异常统一处理

全局异常处理⽅式⼀: 1、配置简单异常处理器 配置 SimpleMappingExceptionResolver 对象: <!-- 配置全局异常统⼀处理的 Bean &#xff08;简单异常处理器&#xff09; --> <bean class"org.springframework.web.servlet.handler.SimpleMappingExceptionReso…

分析电平转换电路导致MCU通讯速率受限的原因

一、问题背景与电平转换电路的重要性 在现代嵌入式系统中,微控制单元(MCU)与其他模块之间的通信速率是关键的性能指标之一。在多种接口通信中,尤其是当不同电平标准的设备进行连接时,电平转换电路成为确保信号正确传输的核心部分。然而,当电平转换电路不匹配时,可能会导…

基于Java Springboot高校工作室管理系统

一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Vue、Element-ui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据…

突破Zustand的局限性:与React ContentAPI搭配使用

Zustand在状态管理中是非常适手的工具&#xff0c;在很多场景中我们都可以用它来解决复杂问题. 但是由于Zustand的设计理念&#xff0c;它仍然有一些限制&#xff0c;在这里用官网中的小demo举一个很简单的例子&#xff1a; import { create } from zustand type CountStore …

YOLOv8实战木材缺陷识别

本文采用YOLOv8作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv8以其高效的实时检测能力&#xff0c;在多个目标检测任务中展现出卓越性能。本研究针对木材缺陷数据集进行训练和优化&#xff0c;该数据集包含丰富的木材缺陷图像样本…

git如何给历史提交打标签

git如何给历史提交打标签 如果忘记给某个提交打标签&#xff0c;可以在之后补上 在项目所在文件夹&#xff0c;右键git bash here 查看历史标签&#xff1a; git tag创建标签&#xff1a; git tag -a 标签名号 commitSHA(历史提交校验码) -m 提交信息 git tag -a v1.0.0.…