[设计模式]行为型-命令模式

简介

命令模式(Command Pattern)是一种行为型设计模式,它将请求或操作封装为独立的对象,允许用户参数化客户端、队列请求、记录日志,并支持撤销操作。该模式的核心思想是将“请求的发起者”与“请求的执行者”解耦,使两者通过命令对象进行交互。

角色组成:

  • 调用者(Invoker),负责发起请求的类
  • 命令(Command),一个接口,通常仅声明一个执行命令的方法
  • 具体命令(ConcretCommand),实现各种类型请求的类
  • 接受者(Receiver),包含部分业务逻辑的接口或类。大部分命令只处理如何将请求传递给接受者的细节,接受者会完成实际的工作。
  • 客户端(Client),创建并配置具体命令对象。

适用场景

  1. 解耦请求发起者与执行者:当需要将操作调用者(如UI控件)与具体实现(如业务逻辑)分离时。
  2. 支持撤销/重做:如文本编辑器、图形软件中的操作历史。
  3. 延迟执行或任务队列:将命令存入队列,按计划或异步执行。
  4. 事务管理:将多个操作组合成原子事务,支持回滚。
  5. 宏命令(组合命令):批量执行一系列命令。

优点

  1. 解耦:调用者与接收者无需直接交互,降低耦合度。
  2. 扩展性:新增命令无需修改现有代码,符合开闭原则。
  3. 支持复杂操作:可轻松实现撤销、重做、事务、宏命令。
  4. 灵活调度:命令可排队、延迟执行或记录日志。

缺点

  1. 类数量增加:每个命令需单独类,可能导致代码膨胀。
  2. 复杂度提升:对简单操作可能过度设计,增加理解成本。
  3. 性能开销:多层间接调用可能影响效率(通常可忽略)。

示例代码

Go

package command

import "fmt"

// 命令 接口
type Command interface {
	Execute()
}

// 调用者类
type Button struct {
	Command Command
}

func (b *Button) Press() {
	b.Command.Execute()
}

// 具体命令类
type OnCommand struct {
	Device Device
}

func (c *OnCommand) Execute() {
	c.Device.On()
}

// 具体命令类
type OffCommand struct {
	Device Device
}

func (c *OffCommand) Execute() {
	c.Device.Off()
}

// 接收者接口
type Device interface {
	On()
	Off()
}

// 具体接受者类
type Light struct {
	isRunning bool
}

func (t *Light) On() {
	t.isRunning = true
	fmt.Println("Light is on")
}

func (t *Light) Off() {
	t.isRunning = false
	fmt.Println("Light is off")
}

客户端

package command

import "testing"

func TestCommand(t *testing.T) {
	Light := &Light{}

	onCommand := &OnCommand{
		Device: Light,
	}

	OffCommand := &OffCommand{
		Device: Light,
	}

	onButton := &Button{
		Command: onCommand,
	}

	onButton.Press()

	offButton := &Button{
		Command: OffCommand,
	}
	offButton.Press()
}

Python

from abc import ABCMeta, abstractmethod


class Command(metaclass=ABCMeta):
    @abstractmethod
    def execute(self):
        pass


class Device(metaclass=ABCMeta):
    @abstractmethod
    def on(self):
        pass

    @abstractmethod
    def off(self):
        pass


class Button:
    def __init__(self, command: Command):
        self.command = command

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


class OnCommand(Command):
    def __init__(self, device: Device):
        self.device = device

    def execute(self):
        self.device.on()


class OffCommand(Command):
    def __init__(self, device: Device):
        self.device = device

    def execute(self):
        self.device.off()


class Light(Device):
    def __init__(self):
        self.is_running = False

    def on(self):
        self.is_running = True
        print("Light is on")

    def off(self):
        self.is_running = False
        print("Light is off")


if __name__ == "__main__":
    light = Light()

    on_command = OnCommand(light)
    off_command = OffCommand(light)
    button = Button(on_command)
    button.press()
    button = Button(off_command)
    button.press()

posted @ 2025-03-31 22:34  花酒锄作田  阅读(84)  评论(0)    收藏  举报