跳转到内容

命令模式

来自代码酷

模板:编程设计模式导航

命令模式(Command Pattern)是一种行为设计模式,它将请求或操作封装为对象,从而使你可以参数化客户端(调用者)与接收者(执行者)之间的交互。这种模式的主要目的是解耦调用者与接收者,支持撤销操作、队列请求或记录日志等功能。

概述[编辑 | 编辑源代码]

命令模式的核心思想是将一个请求封装成一个对象,从而使不同的请求、队列或日志请求参数化其他对象。该模式包含以下几个关键角色:

  • 命令接口(Command):声明执行操作的接口。
  • 具体命令(ConcreteCommand):实现命令接口,绑定一个接收者对象及其动作。
  • 接收者(Receiver):知道如何执行与请求相关的操作。
  • 调用者(Invoker):存储命令对象并在适当时机调用命令。
  • 客户端(Client):创建具体命令对象并设置其接收者。

命令模式的类图可以用以下结构表示:

classDiagram class Command { +execute() } class ConcreteCommand { -receiver: Receiver +execute() } class Receiver { +action() } class Invoker { -command: Command +setCommand(Command) +executeCommand() } class Client { } Command <|-- ConcreteCommand ConcreteCommand o-- Receiver Invoker o-- Command Client ..> ConcreteCommand Client ..> Receiver

代码示例[编辑 | 编辑源代码]

以下是一个简单的命令模式实现示例,模拟一个遥控器控制电灯开关的场景:

Java 示例[编辑 | 编辑源代码]

// 命令接口
interface Command {
    void execute();
}

// 接收者:电灯
class Light {
    public void turnOn() {
        System.out.println("Light is ON");
    }

    public void turnOff() {
        System.out.println("Light is OFF");
    }
}

// 具体命令:开灯命令
class TurnOnCommand implements Command {
    private Light light;

    public TurnOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOn();
    }
}

// 具体命令:关灯命令
class TurnOffCommand implements Command {
    private Light light;

    public TurnOffCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.turnOff();
    }
}

// 调用者:遥控器
class RemoteControl {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void pressButton() {
        command.execute();
    }
}

// 客户端代码
public class CommandPatternDemo {
    public static void main(String[] args) {
        Light light = new Light();
        Command turnOn = new TurnOnCommand(light);
        Command turnOff = new TurnOffCommand(light);

        RemoteControl remote = new RemoteControl();

        remote.setCommand(turnOn);
        remote.pressButton(); // 输出: Light is ON

        remote.setCommand(turnOff);
        remote.pressButton(); // 输出: Light is OFF
    }
}

Python 示例[编辑 | 编辑源代码]

from abc import ABC, abstractmethod

# 命令接口
class Command(ABC):
    @abstractmethod
    def execute(self):
        pass

# 接收者:电灯
class Light:
    def turn_on(self):
        print("Light is ON")

    def turn_off(self):
        print("Light is OFF")

# 具体命令:开灯命令
class TurnOnCommand(Command):
    def __init__(self, light):
        self.light = light

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

# 具体命令:关灯命令
class TurnOffCommand(Command):
    def __init__(self, light):
        self.light = light

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

# 调用者:遥控器
class RemoteControl:
    def __init__(self):
        self.command = None

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

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

# 客户端代码
if __name__ == "__main__":
    light = Light()
    turn_on = TurnOnCommand(light)
    turn_off = TurnOffCommand(light)

    remote = RemoteControl()

    remote.set_command(turn_on)
    remote.press_button()  # 输出: Light is ON

    remote.set_command(turn_off)
    remote.press_button()  # 输出: Light is OFF

实际应用场景[编辑 | 编辑源代码]

命令模式在以下场景中特别有用:

1. GUI 按钮和菜单项:每个按钮点击或菜单选择可以绑定到一个命令对象。 2. 事务系统:支持撤销/重做操作,每个操作被封装为命令对象。 3. 任务队列:将请求排队并按顺序执行。 4. 宏命令:组合多个命令成为一个复合命令。

撤销操作示例[编辑 | 编辑源代码]

命令模式可以扩展以支持撤销操作。以下是支持撤销的 Java 实现:

interface Command {
    void execute();
    void undo();
}

class Light {
    private boolean isOn = false;

    public void turnOn() {
        isOn = true;
        System.out.println("Light is ON");
    }

    public void turnOff() {
        isOn = false;
        System.out.println("Light is OFF");
    }

    public boolean isOn() {
        return isOn;
    }
}

class ToggleCommand implements Command {
    private Light light;

    public ToggleCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        if (light.isOn()) {
            light.turnOff();
        } else {
            light.turnOn();
        }
    }

    @Override
    public void undo() {
        if (light.isOn()) {
            light.turnOff();
        } else {
            light.turnOn();
        }
    }
}

// 使用示例
public class UndoDemo {
    public static void main(String[] args) {
        Light light = new Light();
        Command toggle = new ToggleCommand(light);
        RemoteControl remote = new RemoteControl();

        remote.setCommand(toggle);
        remote.pressButton(); // 开灯
        remote.pressButton(); // 关灯
        ((ToggleCommand)toggle).undo(); // 撤销最后一次操作(重新开灯)
    }
}

优缺点[编辑 | 编辑源代码]

优点[编辑 | 编辑源代码]

  • 解耦调用者与接收者。
  • 支持撤销/重做操作。
  • 可以将命令组合成复合命令(宏命令)。
  • 新的命令可以很容易地添加到系统中。

缺点[编辑 | 编辑源代码]

  • 可能会导致系统中出现大量的具体命令类。
  • 增加了系统的复杂性。

与其他模式的关系[编辑 | 编辑源代码]

  • 责任链模式:可以将多个命令对象链接起来。
  • 备忘录模式:可用于实现命令的撤销操作。
  • 组合模式:可用于实现宏命令。
  • 策略模式:命令模式与策略模式都涉及封装行为,但命令模式侧重于动作的执行和撤销,而策略模式侧重于算法的替换。

总结[编辑 | 编辑源代码]

命令模式是一种强大的行为设计模式,特别适用于需要将操作请求与执行解耦的场景。通过将请求封装为对象,我们可以轻松实现撤销、重做、队列和日志等功能。虽然它可能增加一些类的数量,但其灵活性和可扩展性使其成为许多软件系统中的重要模式。

模板:编程设计模式导航