模拟一个多功能遥控器,一件开关灯和空调。
如果不使用命令模式,遥控器与电器耦合在一起,如果再增加一个电器,就需要修改遥控器类,违反开闭原则。
如果不使用命令模式也不能实现undo和redo功能。
package command;
public interface Appliance {
void on();
void off();
}
package command;
public class Light implements Appliance{
@Override
public void on() {
System.out.println("开灯");
}
@Override
public void off() {
System.out.println("关灯");
}
}
package command;
public class AirConditioner implements Appliance{
@Override
public void on() {
System.out.println("打开空调");
}
@Override
public void off() {
System.out.println("关闭空调");
}
}
package command;
public abstract class Command {
Appliance appliance;
public Command(Appliance appliance) {
super();
this.appliance = appliance;
}
//执行
public abstract void execute();
//撤销
public abstract void undo();
}
package command;
public class LightOnCommand extends Command{
public LightOnCommand(Light light) {
super(light);
}
@Override
public void execute() {
appliance.on();
}
@Override
public void undo() {
appliance.off();
}
}
package command;
public class LightOffCommand extends Command{
public LightOffCommand(Light light) {
super(light);
}
@Override
public void execute() {
appliance.off();
}
@Override
public void undo() {
appliance.on();
}
}
package command;
public class AirConditionerOnCommand extends Command{
public AirConditionerOnCommand(Appliance appliance) {
super(appliance);
}
@Override
public void execute() {
appliance.on();
}
@Override
public void undo() {
appliance.off();
}
}
package command;
public class AirConditionerOffCommand extends Command{
public AirConditionerOffCommand(Appliance appliance) {
super(appliance);
}
@Override
public void execute() {
appliance.off();
}
@Override
public void undo() {
appliance.on();
}
}
package command;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class RemoteInvoker {
//开命令
private List<Command> onCommands=new ArrayList<>();
//关命令
private List<Command> offCommands=new ArrayList<>();
//撤回命令
private Stack<List<Command>> undoCommands=new Stack<>();
//重新执行命令
private Stack<List<Command>> redoCommands=new Stack<>();
//添加开命令
public void addOnCommand(Command onCommand) {
onCommands.add(onCommand);
}
//添加关命令
public void addOffCommand(Command offCommand) {
offCommands.add(offCommand);
}
//打开开关,执行开命令
public void pressOnButton() {
onCommands.stream().forEach(Command::execute);
undoCommands.push(onCommands);
redoCommands.clear();
}
//关闭开关,执行关命令
public void pressOffButton() {
offCommands.stream().forEach(Command::execute);
undoCommands.push(offCommands);
redoCommands.clear();
}
//撤销
public void undo() {
List<Command> commands=undoCommands.pop();
commands.stream().forEach(Command::undo);
redoCommands.push(commands);
}
//重新执行
public void redo() {
List<Command> commands=redoCommands.pop();
commands.stream().forEach(Command::execute);
undoCommands.push(commands);
}
}
package command;
public class CommandTest {
public static void main(String[] args) {
//demo的构建思路:
//1.构建单命令demo
//2.添加多命令
//3.添加多命令单回退
//4.添加多命令多回退
//5.添加重新执行
Light light=new Light();
AirConditioner airConditioner=new AirConditioner();
Command lightOnCommand=new LightOnCommand(light);
Command lightOffCommand=new LightOffCommand(light);
Command airConditionerOnCommand=new AirConditionerOnCommand(airConditioner);
Command airConditionerOffCommand=new AirConditionerOffCommand(airConditioner);
RemoteInvoker remoteInvoker=new RemoteInvoker();
remoteInvoker.addOnCommand(lightOnCommand);
remoteInvoker.addOffCommand(lightOffCommand);
remoteInvoker.addOnCommand(airConditionerOnCommand);
remoteInvoker.addOffCommand(airConditionerOffCommand);
remoteInvoker.pressOnButton();
remoteInvoker.pressOffButton();
remoteInvoker.pressOnButton();
remoteInvoker.pressOffButton();
remoteInvoker.undo();
remoteInvoker.undo();
remoteInvoker.undo();
remoteInvoker.undo();
remoteInvoker.redo();
remoteInvoker.pressOffButton();
}
}
打印结果:
开灯
打开空调
关灯
关闭空调
开灯
打开空调
关灯
关闭空调
开灯
打开空调
关灯
关闭空调
开灯
打开空调
关灯
关闭空调
开灯
打开空调
关灯
关闭空调
小结:
1.命令模式的好处是将调用者(Invoker)与实际实现功能的对象进行解耦,同时能够实现撤销和重做的功能。