【设计模式】【行为型模式(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. 性能开销:命令模式可能会带来一些性能开销,特别是在命令对象较多时。
适用场景
  • 当需要将请求排队或记录请求日志,或者支持可撤销操作时。
  • 当需要参数化对象来指定要执行的操作时。
  • 当需要在不同的时刻指定、排列和执行请求时。
  • 当需要将请求发送者与接收者解耦时。
相关推荐
博风1 小时前
设计模式:11、迭代器模式(游标)
设计模式·迭代器模式
请你打开电视看看2 小时前
行为型模式-命令模式
命令模式
岳轩子5 小时前
23种设计模式之原型模式
设计模式·原型模式
十五年专注C++开发5 小时前
C++中的链式操作原理与应用(一)
开发语言·c++·设计模式
旺代7 小时前
C++设计模式(单例模式)
c++·单例模式·设计模式
LightOfNight7 小时前
【设计模式】创建型模式之单例模式(饿汉式 懒汉式 Golang实现)
单例模式·设计模式·golang
那年星空16 小时前
Flutter 设计模式全面解析:抽象工厂
flutter·设计模式·架构
博风18 小时前
设计模式:10、外观模式
设计模式·外观模式
你好helloworld20 小时前
设计模式之观察者模式
观察者模式·设计模式