Java命令模式简介及示例

1. 引言

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

命令模式中的主要角色有:命令接口(Command Interface)、具体命令(Concrete Command)、命令调用者(Command Invoker)和接收者(Receiver)。

本文将通过一个示例来详细介绍Java命令模式的使用。

2. 示例场景

假设我们正在开发一个简单的遥控器应用程序。遥控器上有几个按钮,每个按钮代表一个电器设备,例如电视、音响等。我们需要实现以下功能:

  • 每个按钮可以执行不同的操作,例如打开、关闭、调高音量、调低音量等;
  • 每个按钮上都有一个撤销按钮,可以撤销上一次的操作。

3. 实现步骤

3.1 命令接口(Command Interface)

我们首先定义一个命令接口,该接口中包含了执行和撤销命令的方法。

// Command Interface
public interface Command {
    void execute();
    void undo();
}

此处定义了execute()方法用于执行命令,undo()方法用于撤销命令。

3.2 具体命令(Concrete Command)

我们为每个按钮创建具体的命令类,每个命令类都实现了命令接口。

// Concrete Command for turning on the TV
public class TurnOnTvCommand implements Command {
    private TV tv;

    public TurnOnTvCommand(TV tv) {
        this.tv = tv;
    }

    public void execute() {
        tv.turnOn();
    }

    public void undo() {
        tv.turnOff();
    }
}

// Concrete Command for increasing the volume of the sound system
public class IncreaseVolumeCommand implements Command {
    private SoundSystem soundSystem;

    public IncreaseVolumeCommand(SoundSystem soundSystem) {
        this.soundSystem = soundSystem;
    }

    public void execute() {
        soundSystem.increaseVolume();
    }

    public void undo() {
        soundSystem.decreaseVolume();
    }
}

// Concrete Command for turning off the TV
public class TurnOffTvCommand implements Command {
    private TV tv;

    public TurnOffTvCommand(TV tv) {
        this.tv = tv;
    }

    public void execute() {
        tv.turnOff();
    }

    public void undo() {
        tv.turnOn();
    }
}

每个具体命令类都有一个接收者对象,用于执行具体的操作。

3.3 接收者(Receiver)

我们为每个电器设备创建一个接收者类,用于实现电器设备的操作。

// Receiver for the TV
public class TV {
    public void turnOn() {
        System.out.println("TV turned on");
    }

    public void turnOff() {
        System.out.println("TV turned off");
    }
}

// Receiver for the Sound System
public class SoundSystem {
    public void increaseVolume() {
        System.out.println("Volume increased");
    }

    public void decreaseVolume() {
        System.out.println("Volume decreased");
    }
}

3.4 命令调用者(Command Invoker)

我们创建一个命令调用者类,用于执行命令和保存命令历史记录。

// Command Invoker
public class RemoteControl {
    private Command[] onCommands;
    private Command[] offCommands;
    private Command undoCommand;

    public RemoteControl() {
        onCommands = new Command[2];
        offCommands = new Command[2];

        Command noCommand = new NoCommand();
        for (int i = 0; i < 2; i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
        undoCommand = noCommand;
    }

    public void setCommand(int slot, Command onCommand, Command offCommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }

    public void pressOnButton(int slot) {
        onCommands[slot].execute();
        undoCommand = onCommands[slot];
    }

    public void pressOffButton(int slot) {
        offCommands[slot].execute();
        undoCommand = offCommands[slot];
    }

    public void pressUndoButton() {
        undoCommand.undo();
    }
}

3.5 测试代码

我们在main方法中进行