fred-ye / summary

my blog
43 stars 9 forks source link

[Design Pattern] 命令模式 #14

Open fred-ye opened 10 years ago

fred-ye commented 10 years ago

命令模式

以下内容是在学习《Head First设计模式》时做的笔记,会根据自己的理解做部份修改。 命令模式将请求封装成命令对象,将请求的对象和执行请求的对象解耦。

示例一

电灯有两种状态,开和关。对于这种情况,封装了两个命令类型,LightOnCommandLightOffCommand。看代码

Command接口的定义

package command;

public interface Command {
    public void execute();
    public void undo();
}
Light类
public class Light {
    public void on() {
        System.out.println("light on");
    }
    public void off() {
        System.out.println("light off");
    }
}

两个命令

public class LightOnCommand implements Command {
    Light light;

    public LightOnCommand(Light light) {
        this.light = light;
    }

    @Override
    public void execute() {
        light.on();
    }

    @Override
    public void undo() {
        light.off();
    }

}
package command;

public class LightOffCommand implements Command {
    Light light;
    public LightOffCommand(Light light) {
        this.light = light;
    }
    @Override
    public void execute() {
        light.off();
    }

    @Override
    public void undo() {
        light.on();
    }

}

调用

package command;

public class Controller {
    public static void main(String args[]) {
        Light light = new Light();
        LightOnCommand lightOnCommond = new LightOnCommand(light);
        lightOnCommond.execute();
        lightOnCommond.undo();
    }
}

对于存在多种状态的情况

如电风扇有多种转速,1,2,3档,和关闭 四种状态。此时在做undo状态处理时就需要知道上一个状态了。

风扇类

package command;

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;
        speed = OFF;
    }

    public void high() {
        speed = HIGH;
        System.out.println("Set speed-->HIGH");
    }

    public void medium() {
        speed = MEDIUM;
        System.out.println("Set speed-->MEDIUM");

    }

    public void low() {
        speed = LOW;
        System.out.println("Set speed-->LOW");
    }

    public void off() {
        speed = OFF;
        System.out.println("Set CeilingFan off");

    }

    public int getSpeed() {
        return speed;
    }

}

风扇的状态

* 状态 1

package command;

public class CeilingFanHighCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;

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

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

    @Override
    public void undo() {
        if (prevSpeed == CeilingFan.HIGH) {
            ceilingFan.high();
        } else if (prevSpeed == CeilingFan.MEDIUM) {
            ceilingFan.medium();
        } else if (prevSpeed == CeilingFan.LOW) {
            ceilingFan.low();
        } else if (prevSpeed == CeilingFan.OFF) {
            ceilingFan.off();
        }

    }
}
package command;

public class CeilingFanMediumCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;
    @Override
    public void execute() {
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.medium();
    }

    @Override
    public void undo() {
        if (prevSpeed == CeilingFan.HIGH) {
            ceilingFan.high();
        } else if (prevSpeed == CeilingFan.MEDIUM){
            ceilingFan.medium();
        } else if (prevSpeed == CeilingFan.LOW) {
            ceilingFan.low();
        } else if (prevSpeed == CeilingFan.OFF) {
            ceilingFan.off();
        }
    }

}

调用

package command;

public class Controller {
    public static void main(String args[]) {
        CeilingFan ceilingFan = new CeilingFan("Living Room");
        CeilingFanHighCommand ceilingFanHighCommand = new CeilingFanHighCommand(ceilingFan);
        ceilingFanHighCommand.execute();
        System.out.println(ceilingFan.speed);
        ceilingFanHighCommand.undo();
        System.out.println(ceilingFan.speed);
    }
}

宏的使用

关于宏我们可以简单理解成就是执行一系列的命令。比如当进一进房间的时间,先要开灯,再开电扇,那么我们可以采用命令来做。

package command;

public class MacroCommand implements Command {
    Command[] commands;

    public MacroCommand(Command[] commands) {
        this.commands = commands;
    }

    @Override
    public void execute() {
        for (Command command : commands) {
            command.execute();
        }
    }
    //假设撤销操作是逆向的。
    @Override
    public void undo() {
        int size = commands.length;
        for (int i = size - 1; i >= 0; i--) {
            commands[i].undo();
        }
    }

}
package command;

public class Controller {
    public static void main(String args[]) {
        CeilingFan ceilingFan = new CeilingFan("Living Room");
        CeilingFanHighCommand ceilingFanHighCommand = new CeilingFanHighCommand(
                ceilingFan);
        Light light = new Light();
        LightOnCommand lightOnCommand = new LightOnCommand(light);
        Command[] partyCommands = { lightOnCommand, ceilingFanHighCommand };
        MacroCommand macroCommand = new MacroCommand(partyCommands);
        macroCommand.execute();
        macroCommand.undo();
    }
}

可以看到输出结果是:

light on
Set speed-->HIGH
Set CeilingFan off
light off