命令模式
简介
命令模式(Command Pattern)是一种行为型设计模式,它将请求或操作封装为独 立的对象,允许用户参数化客户端、队列请求、记录日志,并支持撤销操作。该模式的核心思想是将“请求的发起者”与“请求的执行者”解耦,使两者通过命令对象进行交互。
角色组成:
- 调用者(Invoker),负责发起请求的类
- 命令(Command),一个接口,通常仅声明一个执行命令的方法
- 具体命令(ConcretCommand),实现各种类型请求的类
- 接受者(Receiver),包含部分业务逻辑的接口或类。大部分命令只处理如何将请求传递给接受者的细节,接受者会完成实际的工作。
- 客户端(Client),创建并配置具体命令对象。
适用场景
- 解耦请求发起者与执行者:当需要将操作调用者(如UI控件)与具体实现(如业务逻辑)分离时。
- 支持撤销/重做:如文本编辑器、图形软件中的操作历史。
- 延迟执行或任务队列:将命令存入队列,按计划或异步执行。
- 事务管理:将多个操作组合成原子事务,支持回滚。
- 宏命令(组合命令):批量执行一系列命令。
优点
- 解耦:调用者与接收者无需直接交互,降低耦合度。
- 扩展性:新增命令无需修改现有代码,符合开闭原则。
- 支持复杂操作:可轻松实现撤销、重做、事务、宏命令。
- 灵活调度:命令可排 队、延迟执行或记录日志。
缺点
- 类数量增加:每个命令需单独类,可能导致代码膨胀。
- 复杂度提升:对简单操作可能过度设计,增加理解成本。
- 性能开销:多层间接调用可能影响效率(通常可忽略)。
示例代码
- Go
- Python
command.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")
}
客户端
command_test.go
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()
}
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()