《HeadFirst设计模式(第二版)》第六章代码——命令模式

代码文件目录:
Command
java 复制代码
package Chapter6_CommandPattern.Command;

/**
 * @Author 竹心
 * @Date 2023/8/6
 **/

public interface Command {
    public void execute();
    public void undo();//撤销该指令
}
CeilingFan
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
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
java 复制代码
命令模式:
    把请求封装成为对象,以便对不同的请求、队列或者日志请求来参数化对象,
    并支持可撤销的操作

命令对象只暴露一个方法:execute(),命令的请求者不会知道执行者具体如何实现指令

当需要将发出请求的对象和能够实行请求的对象解耦合的时候可以使用命令模式
相关推荐
信徒_几秒前
常用设计模式
java·单例模式·设计模式
神仙别闹6 分钟前
基于C#实现的(WinForm)模拟操作系统文件管理系统
java·git·ffmpeg
小爬虫程序猿7 分钟前
利用Java爬虫速卖通按关键字搜索AliExpress商品
java·开发语言·爬虫
组合缺一12 分钟前
Solon v3.0.5 发布!(Spring 可以退休了吗?)
java·后端·spring·solon
程序猿零零漆14 分钟前
SpringCloud 系列教程:微服务的未来(二)Mybatis-Plus的条件构造器、自定义SQL、Service接口基本用法
java·spring cloud·mybatis-plus
猿来入此小猿16 分钟前
基于SpringBoot在线音乐系统平台功能实现十二
java·spring boot·后端·毕业设计·音乐系统·音乐平台·毕业源码
愤怒的代码30 分钟前
Spring Boot对访问密钥加解密——HMAC-SHA256
java·spring boot·后端
带多刺的玫瑰30 分钟前
Leecode刷题C语言之切蛋糕的最小总开销①
java·数据结构·算法
栗豆包1 小时前
w118共享汽车管理系统
java·spring boot·后端·spring·tomcat·maven
夜半被帅醒1 小时前
MySQL 数据库优化详解【Java数据库调优】
java·数据库·mysql