代码文件目录:
Command
package Chapter6_CommandPattern.Command;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public interface Command {
public void execute();
public void undo();//撤销该指令
}
CeilingFan
package Chapter6_CommandPattern.ElectricAppliance;
/**
* @Author 竹心
* @Date 2023/8/6
**/
//吊扇
public class CeilingFan {
public static final int HIGH = 3;
public static final int MEDIUM = 2;
public static final int LOW = 1;
public static final int OFF = 0;
String location;
int speed;
public CeilingFan(String location){
this.location = location;
this.speed = OFF;
}
public void high(){
this.speed = HIGH;
System.out.println(this.location+" ceilingFan is on High");
}
public void medium(){
this.speed = MEDIUM;
System.out.println(this.location+" ceilingFan is on Medium");
}
public void low(){
this.speed = LOW;
System.out.println(this.location+" ceilingFan is on Low");
}
public void off(){
this.speed = OFF;
System.out.println(this.location+" ceilingFan is on Off");
}
public int getSpeed(){
return this.speed;
}
}
CeilingFanHighCommand
package Chapter6_CommandPattern.Command;
import Chapter6_CommandPattern.ElectricAppliance.CeilingFan;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class CeilingFanHighCommand implements Command{
CeilingFan ceilingFan;
int prevSpeed;//保存上一个挡位
public CeilingFanHighCommand(CeilingFan ceilingFan){
this.ceilingFan = ceilingFan;
}
@Override
public void execute() {
this.prevSpeed = this.ceilingFan.getSpeed();
this.ceilingFan.high();
}
@Override
public void undo() {
if(this.prevSpeed==CeilingFan.HIGH){
this.ceilingFan.high();
}else if(this.prevSpeed == CeilingFan.MEDIUM){
this.ceilingFan.medium();
}else if(this.prevSpeed == CeilingFan.LOW){
this.ceilingFan.low();
}else if(this.prevSpeed == CeilingFan.OFF){
this.ceilingFan.off();
}
}
}
Light
package Chapter6_CommandPattern.ElectricAppliance;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class Light {
String name;
public Light(String name){
this.name = name;
}
public void on(){
System.out.println(this.name+" light is on!");
}
public void off(){
System.out.println(this.name+" light is off!");
}
}
LightOnCommand
package Chapter6_CommandPattern.Command;
import Chapter6_CommandPattern.Command.Command;
import Chapter6_CommandPattern.ElectricAppliance.Light;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class LightOnCommand implements Command {
Light light;
public LightOnCommand(Light light){
this.light = light;
}
@Override
public void execute() {
//当遥控器运行这个指令的时候,并不知道灯是如何实现打开开关的
//实现遥控器与电器之间的解耦合
this.light.on();
}
@Override
public void undo() {
this.light.off();
}
}
LightOffCommand
package Chapter6_CommandPattern.Command;
import Chapter6_CommandPattern.ElectricAppliance.Light;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class LightOffCommand implements Command{
Light light;
public LightOffCommand(Light light){
this.light = light;
}
@Override
public void execute() {
this.light.off();
}
public void undo() {
this.light.on();
}
}
GarageDoor
package Chapter6_CommandPattern.ElectricAppliance;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class GarageDoor {
Light light;
public GarageDoor(Light light){
this.light = light;
}
public void up(){
this.lightOn();
System.out.println("the garage door is open!");
}
public void down(){
this.lightOff();
System.out.println("the garage door is closed");
}
private void lightOn(){
this.light.on();
}
private void lightOff(){
this.light.off();
}
}
GarageDoorOpenCommand
package Chapter6_CommandPattern.Command;
import Chapter6_CommandPattern.ElectricAppliance.GarageDoor;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class GarageDoorOpenCommand implements Command{
GarageDoor garageDoor;
public GarageDoorOpenCommand(GarageDoor garageDoor){
this.garageDoor = garageDoor;
}
@Override
public void execute() {
this.garageDoor.up();
}
public void undo() {
this.garageDoor.down();
}
}
GarageDoorCloseCommand
package Chapter6_CommandPattern.Command;
import Chapter6_CommandPattern.ElectricAppliance.GarageDoor;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class GarageDoorCloseCommand implements Command{
GarageDoor garageDoor;
public GarageDoorCloseCommand(GarageDoor garageDoor){
this.garageDoor = garageDoor;
}
@Override
public void execute() {
this.garageDoor.down();
}
public void undo() {
this.garageDoor.down();
}
}
Stereo
package Chapter6_CommandPattern.ElectricAppliance;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class Stereo {
int volume;
//音响类
public void on(){
System.out.println("the stereo is on!");
}
public void off(){
System.out.println("the stereo is off!");
}
public void setCD(){
System.out.println("the stereo can work with CD now!");
}
public void setDVD(){
System.out.println("the stereo can work with DVD now!");
}
public void setVolume(int volume){//设置音量
this.volume = volume;
}
}
StereoOnWithCDCommand
package Chapter6_CommandPattern.Command;
import Chapter6_CommandPattern.ElectricAppliance.Stereo;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class StereoOnWithCDCommand implements Command{
Stereo stereo;
public StereoOnWithCDCommand(Stereo stereo){
this.stereo = stereo;
}
@Override
public void execute() {
this.stereo.on();
this.stereo.setCD();
this.stereo.setVolume(6);
}
@Override
public void undo() {
this.stereo.off();
}
}
StereoOff
package Chapter6_CommandPattern.Command;
import Chapter6_CommandPattern.ElectricAppliance.Stereo;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class StereoOff implements Command{
Stereo stereo;
public StereoOff(Stereo stereo){
this.stereo = stereo;
}
@Override
public void execute() {
this.stereo.off();
}
public void undo() {
this.stereo.on();
this.stereo.setCD();
this.stereo.setVolume(6);
}
}
MacroCommand
package Chapter6_CommandPattern.Command;
/**
* @Author 竹心
* @Date 2023/8/6
**/
//宏指令
public class MacroCommand implements Command{
Command[] commands;
public MacroCommand(Command[] commands){
this.commands = commands;
}
@Override
public void execute() {
for(int i=0;i<this.commands.length;++i){
this.commands[i].execute();
}
}
@Override
public void undo() {
for(int i=0;i<this.commands.length;++i){
this.commands[i].undo();
}
}
}
NoCommand
package Chapter6_CommandPattern.Command;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class NoCommand implements Command{
@Override
public void execute() {
//this command is useless!
}
@Override
public void undo() {
}
}
RemoteControl
package Chapter6_CommandPattern;
import Chapter6_CommandPattern.Command.Command;
import Chapter6_CommandPattern.Command.NoCommand;
import java.util.Arrays;
/**
* @Author 竹心
* @Date 2023/8/6
**/
//遥控器类
public class RemoteControl {
Command[] onCommands;
Command[] offCommands;
Command undoCommand;
public RemoteControl(){
//为简洁起见,这里遥控器只有3个槽位
this.onCommands = new Command[7];
this.offCommands = new Command[7];
Command noCommand = new NoCommand();
//这里使用空对象,是为了后面不用写 if(onCommand[i]==null){...}
for(int i =0;i<7;++i){
this.onCommands[i] = noCommand;
this.offCommands[i] = noCommand;
}
this.undoCommand = noCommand;
}
//设置某个电器的开关命令
public void setCommand(int slot, Command onCommand, Command offCommand){
this.onCommands[slot] = onCommand;
this.offCommands[slot] = offCommand;
}
public void onButtonWasPushed(int slot){
this.onCommands[slot].execute();
this.undoCommand = this.onCommands[slot];
}
public void offButtonWasPushed(int slot){
this.offCommands[slot].execute();
this.undoCommand = this.offCommands[slot];
}
public void undoButtonWasPushed(){
this.undoCommand.undo();
}
@Override
public String toString() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("\n---------- Remote Control ----------\n");
for(int i = 0;i<this.onCommands.length;i++){
stringBuffer.append("[slot "+ i +"] "+
String.format("%-30s",this.onCommands[i].getClass().getSimpleName())+
String.format("%-30s",this.offCommands[i].getClass().getSimpleName())+"\n"
);
}
stringBuffer.append("[undo] "+this.undoCommand.getClass().getSimpleName());
return stringBuffer.toString();
}
}
RemoteLoader
package Chapter6_CommandPattern;
import Chapter6_CommandPattern.Command.*;
import Chapter6_CommandPattern.ElectricAppliance.CeilingFan;
import Chapter6_CommandPattern.ElectricAppliance.GarageDoor;
import Chapter6_CommandPattern.ElectricAppliance.Light;
import Chapter6_CommandPattern.ElectricAppliance.Stereo;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class RemoteLoader {
public static void main(String[] args) {
RemoteControl remoteControl = new RemoteControl();
//创建设备
Light LivingRoomLight = new Light("LivingRoom");
Light KitchenLight = new Light("Kitchen");
Light GarageLight = new Light("Garage");
GarageDoor garageDoor = new GarageDoor(GarageLight);
Stereo stereo = new Stereo();
//创建命令对象
LightOnCommand livingRoomLightOn =new LightOnCommand(LivingRoomLight);
LightOnCommand kitchenLightOn = new LightOnCommand(KitchenLight);
GarageDoorOpenCommand garageDoorOpenCommand =
new GarageDoorOpenCommand(garageDoor);
StereoOnWithCDCommand stereoOnWithCDCommand =
new StereoOnWithCDCommand(stereo);
LightOffCommand lightOffCommand = new LightOffCommand(LivingRoomLight);
LightOffCommand kitchenLightOff = new LightOffCommand(KitchenLight);
GarageDoorCloseCommand garageDoorCloseCommand =
new GarageDoorCloseCommand(garageDoor);
StereoOff stereoOff = new StereoOff(stereo);
//将命令加载进入槽位
remoteControl.setCommand(0,livingRoomLightOn,lightOffCommand);
remoteControl.setCommand(1,kitchenLightOn,kitchenLightOff);
remoteControl.setCommand(2,garageDoorOpenCommand,garageDoorCloseCommand);
remoteControl.setCommand(3,stereoOnWithCDCommand,stereoOff);
//展示
// System.out.println(remoteControl);
remoteControl.onButtonWasPushed(0);
remoteControl.onButtonWasPushed(1);
remoteControl.onButtonWasPushed(2);
remoteControl.onButtonWasPushed(3);
remoteControl.offButtonWasPushed(0);
remoteControl.offButtonWasPushed(1);
remoteControl.offButtonWasPushed(2);
remoteControl.offButtonWasPushed(3);
//使用lambda简洁编写代码
//增加撤销按钮后就不能使用了
//这样就不用写一大堆命令类了
// remoteControl.setCommand(4,()->LivingRoomLight.on(),
// ()->LivingRoomLight.off());
//测试撤销功能
System.out.println("\n测试撤销:");
remoteControl.onButtonWasPushed(0);
remoteControl.undoButtonWasPushed();
//测试风扇
System.out.println("test fan");
CeilingFan ceilingFan = new CeilingFan("livingRoom");
CeilingFanHighCommand command = new CeilingFanHighCommand(ceilingFan);
remoteControl.setCommand(4,command,command);
System.out.println(remoteControl);
remoteControl.onButtonWasPushed(4);
System.out.println(remoteControl);
remoteControl.undoButtonWasPushed();
//测试宏指令
System.out.println("\n宏指令");
Light light1 = new Light("Room1");
Light light2 = new Light("Room2");
Light light3 = new Light("Room3");
Light light4 = new Light("Room4");
LightOnCommand lightOnCommand1 = new LightOnCommand(light1);
LightOnCommand lightOnCommand2 = new LightOnCommand(light2);
LightOnCommand lightOnCommand3 = new LightOnCommand(light3);
LightOnCommand lightOnCommand4 = new LightOnCommand(light4);
LightOffCommand lightOffCommand1 = new LightOffCommand(light1);
LightOffCommand lightOffCommand2 = new LightOffCommand(light2);
LightOffCommand lightOffCommand3 = new LightOffCommand(light3);
LightOffCommand lightOffCommand4 = new LightOffCommand(light4);
Command[] onCommands = {lightOnCommand1,lightOnCommand2,lightOnCommand3,lightOnCommand4};
Command[] offCommand = {lightOffCommand1,lightOffCommand2,lightOffCommand3,lightOffCommand4};
MacroCommand partyOn = new MacroCommand(onCommands);
MacroCommand partyOff = new MacroCommand(offCommand);
remoteControl.setCommand(5,partyOn,partyOff);
System.out.println(remoteControl);
remoteControl.onButtonWasPushed(5);
remoteControl.offButtonWasPushed(5);
remoteControl.undoButtonWasPushed();
}
}
SimpleRemoteControl
package Chapter6_CommandPattern;
import Chapter6_CommandPattern.Command.Command;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class SimpleRemoteControl {
Command slot;//目前该遥控器只支持一个槽位
public SimpleRemoteControl(){}
public void setCommand(Command command){
this.slot = command;
}
public void buttonWasPressed(){
this.slot.execute();
}
}
RemoteControlTest
package Chapter6_CommandPattern;
import Chapter6_CommandPattern.Command.GarageDoorOpenCommand;
import Chapter6_CommandPattern.ElectricAppliance.GarageDoor;
import Chapter6_CommandPattern.ElectricAppliance.Light;
/**
* @Author 竹心
* @Date 2023/8/6
**/
public class RemoteControlTest {
public static void main(String[] args) {
SimpleRemoteControl remote = new SimpleRemoteControl();
Light light = new Light("garage light");
GarageDoor garageDoor = new GarageDoor(light);
GarageDoorOpenCommand garageDoorOpen = new GarageDoorOpenCommand(garageDoor);
remote.setCommand(garageDoorOpen);
remote.buttonWasPressed();
}
}
notes.txt
命令模式:
把请求封装成为对象,以便对不同的请求、队列或者日志请求来参数化对象,
并支持可撤销的操作
命令对象只暴露一个方法:execute(),命令的请求者不会知道执行者具体如何实现指令
当需要将发出请求的对象和能够实行请求的对象解耦合的时候可以使用命令模式