设计模式实战:命令模式(Command)

在很多系统中,你会遇到这样的需求:

  • 把"操作"当成对象传递
  • 支持操作的撤销(Undo)
  • 支持操作队列 / 延迟执行
  • 支持日志记录与重放

例如:

  • 编辑器的撤销/重做
  • 任务队列(异步执行)
  • 按钮点击绑定不同行为
  • 审批操作记录

如果直接写函数调用:

python 复制代码
light.turn_on()
light.turn_off()

看起来简单,但问题是:

  • 操作无法记录
  • 无法撤销
  • 无法统一调度

这时候就需要 ------ 命令模式(Command)


一、命令模式解决什么问题?

一句话:

将请求封装为对象,从而使你可以用不同的请求对客户进行参数化。

关键词:

  • 请求封装
  • 解耦调用者与执行者
  • 支持撤销/重做
  • 支持队列

二、核心角色

命令模式包含四个角色:

1️⃣ Command(命令接口)

定义执行操作的接口。

2️⃣ ConcreteCommand(具体命令)

实现具体操作,绑定接收者。

3️⃣ Receiver(接收者)

真正执行动作的对象。

4️⃣ Invoker(调用者)

触发命令执行。

结构:

复制代码
Invoker → Command → Receiver

三、一个典型场景:智能家居控制

我们用"控制灯"作为例子。


四、Python 实现命令模式

1️⃣ 接收者(Receiver)

python 复制代码
class Light:

    def turn_on(self):
        print("灯打开")

    def turn_off(self):
        print("灯关闭")

2️⃣ 命令接口

python 复制代码
from abc import ABC, abstractmethod

class Command(ABC):

    @abstractmethod
    def execute(self):
        pass

3️⃣ 具体命令

python 复制代码
class TurnOnCommand(Command):

    def __init__(self, light: Light):
        self.light = light

    def execute(self):
        self.light.turn_on()


class TurnOffCommand(Command):

    def __init__(self, light: Light):
        self.light = light

    def execute(self):
        self.light.turn_off()

4️⃣ 调用者(Invoker)

python 复制代码
class RemoteControl:

    def __init__(self):
        self.command = None

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

    def press_button(self):
        self.command.execute()

5️⃣ 使用方式

python 复制代码
light = Light()

on_command = TurnOnCommand(light)
off_command = TurnOffCommand(light)

remote = RemoteControl()

remote.set_command(on_command)
remote.press_button()

remote.set_command(off_command)
remote.press_button()

输出:

复制代码
灯打开
灯关闭

五、命令模式的核心价值

命令模式本质是:

把"操作"变成对象。

这样带来的好处:

  • 操作可以存储
  • 操作可以传递
  • 操作可以组合
  • 操作可以撤销

六、实现撤销(Undo)

命令模式一个重要能力:撤销操作。

修改命令接口:

python 复制代码
class Command(ABC):

    @abstractmethod
    def execute(self):
        pass

    @abstractmethod
    def undo(self):
        pass

实现:

python 复制代码
class TurnOnCommand(Command):

    def __init__(self, light):
        self.light = light

    def execute(self):
        self.light.turn_on()

    def undo(self):
        self.light.turn_off()

Invoker 记录历史:

python 复制代码
class RemoteControl:

    def __init__(self):
        self.history = []

    def execute(self, command):
        command.execute()
        self.history.append(command)

    def undo(self):
        if self.history:
            command = self.history.pop()
            command.undo()

使用:

python 复制代码
remote = RemoteControl()

cmd = TurnOnCommand(light)

remote.execute(cmd)
remote.undo()

七、命令模式 vs 策略模式

很多人会混淆。

区别很关键:

对比点 命令模式 策略模式
关注点 请求封装 算法替换
是否记录操作
是否支持撤销

一句话:

策略是"怎么做",

命令是"做什么"。


八、命令模式 vs 观察者模式

对比点 命令模式 观察者模式
调用方式 主动触发 被动通知
关系 一对一 一对多

一句话:

命令是"我让你做",

观察者是"发生了你自己处理"。


九、真实项目中的应用

非常常见:

1️⃣ 任务队列

例如:

  • Celery
  • 异步任务系统

每个任务本质就是一个命令。


2️⃣ 撤销/重做系统

例如:

  • 文本编辑器
  • 图形编辑器

3️⃣ 审计日志

记录用户操作:

python 复制代码
delete_user(1001)

可以记录为命令对象,后续回放。


4️⃣ UI 按钮绑定

按钮:

python 复制代码
button.onClick = command.execute

十、更 Pythonic 的写法(函数版)

Python 中可以不用类。

直接用函数:

python 复制代码
def turn_on():
    print("灯打开")

def turn_off():
    print("灯关闭")

Invoker:

python 复制代码
class Remote:

    def __init__(self):
        self.commands = []

    def execute(self, cmd):
        cmd()
        self.commands.append(cmd)

简单直接。


十一、优缺点

✅ 优点

  • 解耦调用者与执行者
  • 支持撤销/重做
  • 支持队列、日志
  • 灵活扩展

❌ 缺点

  • 类数量增加
  • 简单场景可能过度设计

十二、什么时候使用命令模式?

适合:

  • 需要记录操作
  • 需要撤销/重做
  • 需要队列执行
  • 操作需要解耦

不适合:

  • 简单函数调用
  • 无需扩展

十三、一句话总结

命令模式的本质是:
把"操作"变成对象,从而实现可记录、可撤销、可扩展。

换句话说:

不要直接调用方法,把调用封装起来。


相关推荐
QQ2422199798 小时前
基于python+微信小程序的家教管理系统_mh3j9
开发语言·python·微信小程序
RSTJ_16259 小时前
PYTHON+AI LLM DAY THREETY-SEVEN
开发语言·人工智能·python
郝学胜-神的一滴9 小时前
深度学习优化核心:梯度下降与网络训练全解析
数据结构·人工智能·python·深度学习·算法·机器学习
Aision_9 小时前
Agent 为什么需要 Checkpoint?
人工智能·python·gpt·langchain·prompt·aigc·agi
清水白石0089 小时前
《Python性能深潜:从对象分配开销到“小对象风暴”的破解之道(含实战与最佳实践)》
开发语言·python
Land032910 小时前
RPA工具选型技术指南:架构差异与实测数据
python·自动化·rpa
kafei_*10 小时前
VScode 添加 UV虚拟环境方法
vscode·python·uv
ximu_polaris11 小时前
设计模式(C++)-行为型模式-中介者模式
c++·设计模式·中介者模式
洛_尘11 小时前
Python 5:使用库
java·前端·python
m0_5967490911 小时前
如何防止SQL拼接漏洞_使用PDO对象实现安全的SQL交互
jvm·数据库·python