【设计模式】【行为型模式(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. 性能开销:命令模式可能会带来一些性能开销,特别是在命令对象较多时。
适用场景
  • 当需要将请求排队或记录请求日志,或者支持可撤销操作时。
  • 当需要参数化对象来指定要执行的操作时。
  • 当需要在不同的时刻指定、排列和执行请求时。
  • 当需要将请求发送者与接收者解耦时。
相关推荐
Engineer邓祥浩2 小时前
设计模式学习(16) 23-14 命令模式
学习·设计模式·命令模式
Maddie_Mo3 小时前
智能体设计模式 第二章:路由模式
设计模式
一条闲鱼_mytube6 小时前
智能体设计模式(五)人机协同-知识检索RAG-智能体间通信
网络·人工智能·设计模式
小码过河.6 小时前
设计模式——建造者模式
单片机·设计模式·建造者模式
小码过河.8 小时前
设计模式——工厂方法模式
设计模式·工厂方法模式
把csdn当日记本的菜鸡8 小时前
Java设计模式简单入门
java·开发语言·设计模式
老蒋每日coding9 小时前
AI Agent 设计模式系列(十一)—— 目标设定和监控模式
人工智能·设计模式·langchain
蔺太微9 小时前
外观模式(Facade Pattern)
设计模式·外观模式
进击的小头9 小时前
C语言实现设计模式的核心基石
c语言·开发语言·设计模式
Engineer邓祥浩9 小时前
设计模式学习(15) 23-13 模版方法模式
java·学习·设计模式