目录

JAVA设计模式命令模式(Command)

引言

什么是命令模式?

主要角色

命令模式的结构

UML类图

接口与实现

命令接口(Command)

具体命令(ConcreteCommand)

接收者(Receiver)

调用者(Invoker)

客户端(Client)

命令模式的优点

命令模式的缺点

应用场景

实际应用场景

示例代码

1. 命令接口 (Command Interface)

2. 具体命令类 (Concrete Command Classes)

3. 接收者类 (Receiver Class)

4. 调用者类 (Invoker Class)

5. 客户端代码 (Client Code)

命令模式的基本结构

示例代码

1. Command 接口

2. ConcreteCommand 类

3. Receiver 类

4. Invoker 类

5. Client 类

总结


JAVA设计模式命令模式(Command)

引言

在软件开发中,设计模式是经过验证的解决方案,用于解决特定的设计问题或重复出现的问题。这些模式可以提高代码的可读性、可维护性和可扩展性。本文将介绍一种行为型设计模式——命令模式(Command Pattern),并探讨其在Java中的实现和应用。

什么是命令模式?

命令模式是一种行为设计模式,它将请求封装成对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。命令模式的核心思想是将“请求”作为一个对象,将操作请求者与操作执行者解耦。

主要角色
  • 命令(Command):声明执行操作的接口。
  • 具体命令(Concrete Command):实现了命令接口,定义了具体的执行逻辑。
  • 接收者(Receiver):执行命令的具体业务逻辑。
  • 调用者(Invoker):负责调用命令对象执行请求。
  • 客户端(Client):创建具体命令对象,并设置其接收者。

命令模式的结构

UML类图
+-------------------+           +---------------------+
|    Invoker        |           |   ConcreteCommand   |
|-------------------|           |---------------------|
| - command: Command|           | - receiver: Receiver|
|-------------------|           |---------------------|
| + setCommand()    |<--+       | + execute()         |
| + invoke()        |   |       +---------------------+
+-------------------+   |       
                        |       +---------------------+
                        |       |      Receiver       |
                        +------>|---------------------|
                                | + action()          |
                                +---------------------+
接口与实现
命令接口(Command)
public interface Command {
    void execute();
}
具体命令(ConcreteCommand)
public class ConcreteCommand implements Command {
    private Receiver receiver;

    public ConcreteCommand(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.action();
    }
}
接收者(Receiver)
public class Receiver {
    public void action() {
        System.out.println("执行具体的操作");
    }
}
调用者(Invoker)
public class Invoker {
    private Command command;

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

    public void invoke() {
        if (command != null) {
            command.execute();
        }
    }
}
客户端(Client)
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.invoke();
    }
}

命令模式的优点

  1. 降低系统的耦合度:通过引入中间层(命令对象),降低了请求发送者和接收者之间的耦合。
  2. 新的命令可以很容易地加入到系统中:只需实现​​Command​​接口即可。
  3. 可以比较容易地设计一个命令队列:因为每个命令都是一个独立的对象,可以方便地将其放入队列中。
  4. 支持撤销操作:可以通过保存命令对象的状态来实现撤销功能。

命令模式的缺点

  1. 可能会导致某些系统有过多的具体命令类:如果系统中有很多命令,会导致类的数量增加。
  2. 使用命令模式可能会导致系统性能下降:因为每次执行命令都需要创建一个新的命令对象。

应用场景

命令模式适用于以下场景:

  • 需要将请求调用者和请求接收者解耦。
  • 需要支持撤销操作。
  • 需要支持命令的组合操作。
  • 需要将请求排队处理。

命令模式是一种非常实用的行为设计模式,它通过将请求封装成对象,使得系统更加灵活和可扩展。通过本文的介绍,希望读者能够理解命令模式的基本概念、结构和应用场景,并能够在实际项目中灵活运用这一模式。

命令模式(Command Pattern)是一种行为设计模式,它将请求封装成对象,从而使你可以用不同的请求、队列或者请求日志参数化其他对象。命令模式也支持可撤销的操作。

实际应用场景

假设我们正在开发一个智能家居系统,用户可以通过手机应用控制家中的各种设备,如灯光、空调和窗帘等。为了实现这些功能,我们可以使用命令模式来封装每个设备的操作。

示例代码
1. 命令接口 (Command Interface)

首先,定义一个命令接口,所有具体的命令类都将实现这个接口。

public interface Command {
    void execute();
    void undo();
}
2. 具体命令类 (Concrete Command Classes)

接下来,为每个设备操作创建具体的命令类。

// 灯光开启命令
public class LightOnCommand implements Command {
    private Light light;

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

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

    @Override
    public void undo() {
        light.off();
    }
}

// 灯光关闭命令
public class LightOffCommand implements Command {
    private Light light;

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

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

    @Override
    public void undo() {
        light.on();
    }
}
3. 接收者类 (Receiver Class)

接收者类是实际执行命令的对象。

public class Light {
    public void on() {
        System.out.println("Light is ON");
    }

    public void off() {
        System.out.println("Light is OFF");
    }
}
4. 调用者类 (Invoker Class)

调用者类负责调用命令对象的 ​​execute​​ 方法。

public class RemoteControl {
    private Command onCommand;
    private Command offCommand;
    private Command undoCommand;

    public RemoteControl() {
        this.undoCommand = new NoCommand(); // 默认的空命令
    }

    public void setOnCommand(Command onCommand) {
        this.onCommand = onCommand;
    }

    public void setOffCommand(Command offCommand) {
        this.offCommand = offCommand;
    }

    public void onButtonWasPushed() {
        onCommand.execute();
        undoCommand = onCommand;
    }

    public void offButtonWasPushed() {
        offCommand.execute();
        undoCommand = offCommand;
    }

    public void undoButtonWasPushed() {
        if (undoCommand != null) {
            undoCommand.undo();
        }
    }

    private static class NoCommand implements Command {
        @Override
        public void execute() {
            // Do nothing
        }

        @Override
        public void undo() {
            // Do nothing
        }
    }
}
5. 客户端代码 (Client Code)

最后,客户端代码将创建具体的命令对象,并将其设置到调用者对象中。

public class CommandPatternDemo {
    public static void main(String[] args) {
        Light livingRoomLight = new Light();

        Command livingRoomLightOn = new LightOnCommand(livingRoomLight);
        Command livingRoomLightOff = new LightOffCommand(livingRoomLight);

        RemoteControl remoteControl = new RemoteControl();
        remoteControl.setOnCommand(livingRoomLightOn);
        remoteControl.setOffCommand(livingRoomLightOff);

        remoteControl.onButtonWasPushed(); // 输出: Light is ON
        remoteControl.offButtonWasPushed(); // 输出: Light is OFF
        remoteControl.undoButtonWasPushed(); // 输出: Light is ON
    }
}

客户端代码创建了具体的命令对象,并将其设置到调用者对象中。调用者对象负责调用命令对象的 ​​execute​​​ 和 ​​undo​​ 方法,从而实现了对设备的控制。这种设计使得系统的扩展性和灵活性大大增强,同时也支持了命令的撤销操作。命令模式(Command Pattern)是行为设计模式的一种,它将请求封装成对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。这种模式有助于解耦请求的发送者和接收者。

命令模式的基本结构
  1. Command(命令接口):声明执行操作的接口。
  2. ConcreteCommand(具体命令类):实现命令接口,定义与接收者相关的绑定操作。
  3. Receiver(接收者):知道如何实施与执行一个请求相关的操作。任何类都可能作为一个接收者。
  4. Invoker(调用者):要求该命令执行这个请求。
  5. Client(客户端):创建一个具体命令对象并设定它的接收者。
示例代码

假设我们有一个简单的家用电器控制系统,可以控制电灯的开关。

1. Command 接口
public interface Command {
    void execute();
}
2. ConcreteCommand 类
public class LightOnCommand implements Command {
    private Light light;

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

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

public class LightOffCommand implements Command {
    private Light light;

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

    @Override
    public void execute() {
        light.turnOff();
    }
}
3. Receiver 类
public class Light {
    public void turnOn() {
        System.out.println("Light is on");
    }

    public void turnOff() {
        System.out.println("Light is off");
    }
}
4. Invoker 类
public class RemoteControl {
    private Command slot;

    public void setCommand(Command command) {
        slot = command;
    }

    public void buttonWasPressed() {
        slot.execute();
    }
}
5. Client 类
public class Client {
    public static void main(String[] args) {
        // 创建接收者
        Light light = new Light();

        // 创建命令对象
        Command lightOn = new LightOnCommand(light);
        Command lightOff = new LightOffCommand(light);

        // 创建调用者
        RemoteControl remoteControl = new RemoteControl();

        // 设置命令
        remoteControl.setCommand(lightOn);
        remoteControl.buttonWasPressed(); // 输出: Light is on

        remoteControl.setCommand(lightOff);
        remoteControl.buttonWasPressed(); // 输出: Light is off
    }
}
总结

通过上述示例,可以看到命令模式的主要优点包括:

  • 低耦合:发送者和接收者之间没有直接的依赖关系,这使得系统更加灵活。
  • 扩展性:可以很容易地增加新的命令,只需要实现 ​​Command​​ 接口即可。
  • 支持撤销操作:可以在 ​​Command​​ 接口中添加 ​​undo()​​ 方法来实现撤销功能。

命令模式在很多框架和库中都有应用,例如在 GUI 应用中处理用户输入、在游戏开发中处理玩家命令等。

更多推荐