继续上部分的说

在之前的文章最后写了一个带有撤销电灯功能的遥控器功能,通常,想要实现撤销的功能,需要记录撤销之前的状态是什么,就比方说电扇,允许有多个风速状态,也允许被关闭。
直接上代码。

1、风扇类

package CeilingFan;
/**
 * 使用状态实现撤销
 * 风扇类
 * @author Joy
 * 
 */
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;
    }

    // 高转速
    public void high() {
        speed = HIGH;
        System.out.println(location+"风扇正在高转速运行");
    }

    // 中转速
    public void medium() {
        speed = MEDIUM;
        System.out.println(location+"风扇正在中转速运行");
    }

    // 低转速
    public void low() {
        speed = LOW;
        System.out.println(location+"风扇正在低转速运行");
    }

    // 关闭吊扇
    public void off() {
        speed = OFF;
        System.out.println(location+"风扇关闭");
    }
    
    //获取当前吊扇速度
    public int getSpeed(){
        return speed;
    }
}

2、命令类

package CeilingFan;

public interface Command {
    public void execute();

    public void undo();
}

3、下面是风扇高、中、低关闭的具体实现类

package CeilingFan;

/**
 * 风扇高速操作
 * 
 * @author Joy
 * 
 */
public class CeilingFanHighCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;

    public CeilingFanHighCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }

    // 执行
    @Override
    public void execute() {
        // 执行方法前,先获取之前的状态并记录下来
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.high();
    }

    // 撤销
    @Override
    public void undo() {
        // 将风扇的速度设置为之前的状态,达到撤销目的
        switch (prevSpeed) {
        case CeilingFan.HIGH:
            ceilingFan.high();
            break;
        case CeilingFan.MEDIUM:
            ceilingFan.medium();
            break;
        case CeilingFan.LOW:
            ceilingFan.low();
            break;
        case CeilingFan.OFF:
            ceilingFan.off();
            break;
        }
    }
}
package CeilingFan;
/**
 * 风扇中速操作
 * @author Joy
 *
 */
public class CeilingFanMediumCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;

    public CeilingFanMediumCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }

    public void execute() {
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.medium();
    }

    public void undo() {
        switch (prevSpeed) {
        case CeilingFan.HIGH:
            ceilingFan.high();
            break;
        case CeilingFan.MEDIUM:
            ceilingFan.medium();
            break;
        case CeilingFan.LOW:
            ceilingFan.low();
            break;
        default:
            ceilingFan.off();
            break;
        }
    }
}
package CeilingFan;
/**
 * 风扇低速操作
 * @author Joy
 *
 */
public class CeilingFanLowCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;

    public CeilingFanLowCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }

    @Override
    public void execute() {
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.low();

    }

    @Override
    public void undo() {
        switch (prevSpeed) {
        case CeilingFan.HIGH:
            ceilingFan.high();
            break;
        case CeilingFan.MEDIUM:
            ceilingFan.medium();
            break;
        case CeilingFan.LOW:
            ceilingFan.low();
            break;
        default:
            ceilingFan.off();
            break;
        }
    }
}
package CeilingFan;
/**
 * 风扇关闭
 * @author Joy
 *
 */
public class CeilingFanOffCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;

    public CeilingFanOffCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }

    public void execute() {
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.off();
    }

    public void undo() {
        switch (prevSpeed) {
        case CeilingFan.HIGH:
            ceilingFan.high();
            break;
        case CeilingFan.MEDIUM:
            ceilingFan.medium();
            break;
        case CeilingFan.LOW:
            ceilingFan.low();
            break;
        default:
            ceilingFan.off();
            break;
        }
    }
}

4、无操作类接口

package CeilingFan;

public class NoCommand implements Command {
    public void execute() { }
    public void undo() { }
}

5、调用者

package CeilingFan;
/**
 * 调用者
 * @author Joy
 *
 */
public class RemoteControlWithUndo {
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;
 
    public RemoteControlWithUndo() {
        onCommands = new Command[7];
        offCommands = new Command[7];
 
        Command noCommand = new NoCommand();
        for(int i=0;i<7;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 onButtonWasPushed(int slot) {
        onCommands[slot].execute();
        undoCommand = onCommands[slot];
    }
 
    public void offButtonWasPushed(int slot) {
        offCommands[slot].execute();
        undoCommand = offCommands[slot];
    }
 
    public void undoButtonWasPushed() {
        undoCommand.undo();
    }
  
    public String toString() {
        StringBuffer stringBuff = new StringBuffer();
        stringBuff.append("\n------ 遥控器 -------\n");
        for (int i = 0; i < onCommands.length; i++) {
            stringBuff.append("[插槽 " + i + "] " + onCommands[i].getClass().getName()
                + "    " + offCommands[i].getClass().getName() + "\n");
        }
        stringBuff.append("[撤销] " + undoCommand.getClass().getName() + "\n");
        return stringBuff.toString();
    }
}

6、测试类

package CeilingFan;

public class TestMain {
    public static void main(String[] args) {
        //实例化遥控器
        RemoteControlWithUndo remoteControl=new RemoteControlWithUndo();
        CeilingFan ceilingFan=new CeilingFan("卧室");
        //这里高中低速 关闭分别实例化
        CeilingFanHighCommand highCommand=new CeilingFanHighCommand(ceilingFan);
        CeilingFanMediumCommand mediumCommand=new CeilingFanMediumCommand(ceilingFan);
        CeilingFanLowCommand  lowCommand=new CeilingFanLowCommand(ceilingFan);
        CeilingFanOffCommand offCommand=new CeilingFanOffCommand(ceilingFan);
        
        //遥控器加载中速和高速的开启和关闭方法
        remoteControl.setCommand(0, mediumCommand, offCommand);
        remoteControl.setCommand(1, highCommand, offCommand);
        //先以中速开启吊扇
        remoteControl.onButtonWasPushed(0);
        //关闭吊扇
        remoteControl.offButtonWasPushed(0);
        //显示插槽调用信息
        System.out.println(remoteControl.toString());
        //撤销,会变为中速
        remoteControl.undoButtonWasPushed();
        
        remoteControl.onButtonWasPushed(1);
        System.out.println(remoteControl.toString());
        remoteControl.undoButtonWasPushed();    
    }
}

7、效果图
图片描述

其实命令模式还能用于宏命令,队列请求,日志请求,命令模式我理解的很一般,往后我还会补充修改此篇内容。

要点:
1:命令模式将发出请求的对象和执行请求的对象解耦。
2:被解耦的两者之间是通过命令对象进行沟通的。命令对象封装了接收者和一个或一组对象
3:调用者通过调用命令对象的execute方法发出请求,这会使得的接收者的动作被调用。
4:命令可以支持撤销动作,实现一个undo方法来回到execute被执行前的状态。

感谢你看到这里,命令模式到这里就结束了,本人文笔随便,若有不足或错误之处望给予指点,90度弯腰~~~很快我会发布下一个设计模式的内容,生命不息,编程不止!


暖心先森
287 声望16 粉丝

生命不息,编程不止!