当前位置: 首页 > article >正文

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

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;
    }

    @Override
    public 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 = receiver

    def execute(self):
        self.receiver.action()

# 调用者
class Invoker:
    def __init__(self):
        self.command = None

    def set_command(self, command):
        self.command = command

    def 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 main

import (
	"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.kler.cn/a/411091.html

相关文章:

  • 计算机网络的发展
  • Taro 鸿蒙技术内幕系列(三) - 多语言场景下的通用事件系统设计
  • Elasticsearch面试内容整理-高级特性
  • C#中的异步操作
  • 【Redis_Day6】Hash类型
  • 研0找实习【学nlp】14--BERT理解
  • Vue进阶面试题(三)
  • Python和R统计检验比较各组之间的免疫浸润
  • 【IEEE出版 | ISBN: 979-8-3315-0796-1 | 高录用稳检索】 2025神经网络与智能优化国际研讨会(NNIO 2025)
  • 中国科学院大学研究生学术英语读写教程 Unit6 Biology TextA 原文和翻译
  • 对于公平与效率的关系问题,材料中有两种不同倾向性的观点,请对这两种观点分别加以概述并谈谈你的看法。字数不超过500字。
  • 上海乐鑫科技一级代理商飞睿科技,ESP32-C61高性价比WiFi6芯片高性能、大容量
  • 鸿蒙应用的基本架构
  • OpenTK 实现三维空间模型仿真详解
  • 基于Springboot的心灵治愈交流平台系统的设计与实现
  • RSA非对称加密解,支持分段加密解密、(公钥加密,私钥解密)、(私钥加密,公钥解密)
  • Bean的生命周期详解保姆级教程,结合spring boot和spring.xml两种方式讲解,5/7/10大小阶段详细分析
  • 基于Matlab卷积神经网络的肺癌检测系统(良性、恶性及正常病例分类的综合分析)
  • 【Vue3+Pinia】Vue新一代状态管理器Pinia
  • 三、计算机视觉_08YOLO目标检测
  • [仓颉Cangjie刷题模板] 优先队列(含小顶堆实现)
  • 开展网络安全成熟度评估:业务分析师的工具和技术
  • postgres-howto 学习笔记
  • 微信小程序学习指南从入门到精通
  • 【2024】前端学习笔记19-ref和reactive使用
  • SpringCloud之Eureka:服务注册与发现全面教程!