Head First设计模式读书笔记五 第六章 命令模式(单例略过)

版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/u011109881/article/details/81915188

本文示例代码材料源自Head First设计模式
以前整理自己整理的链接:
https://blog.csdn.net/u011109881/article/details/59675658

极简命令模式示例代码

命令类:

public interface Command {
    public void execute();
}
public class LightOnCommand implements Command{

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

}

bean:

public class Light {
    String name;

    public Light(String name) {
        this.name = name;
    }

    public void on() {
        System.out.println(name+" light on");
    }

    public void off() {
        System.out.println(name +" light off");
    }
}
public class SimpleRemoteControl {
    Command comm;

    public SimpleRemoteControl() {
    }

    public void setCommand(Command comm){
        this.comm = comm;
    }

    public void buttonWasPressed(){
        comm.execute();
    }

}

测试类:

public class Test {
    public static void main(String[] args) {
        SimpleRemoteControl control = new SimpleRemoteControl();
        Command comm = new LightOnCommand(new Light("白炽灯"));
        control.setCommand(comm);
        control.buttonWasPressed();
    }
}

示例思路(类图)

这里写图片描述
这里写图片描述

解析

将命令封装成对象,传给遥控器,遥控器可以通过命令操作其他事物。
主要角色:
被操控者(例如灯对象) 命令对象(例如开灯命令 关灯命令) 操控者(遥控器)
三者关系:
创建命令对象时,包含了被操控者的实例;创建操控者时,包含了命令对象的实例。因此,操控者和被操控者实现了间接依赖,即,操控者和被操控者实现了解耦。

命令模式升级 遥控器功能丰富化 添加撤销功能

首先,对SimpleRemoteControl类稍作修改,让他可以有很多命令

public class SimpleRemoteControl {
    List<Command> onCommandList;
    List<Command> offCommandList;
    Command undoCmmand;

    public SimpleRemoteControl() {
        onCommandList = new ArrayList<Command>();
        offCommandList = new ArrayList<Command>();
    }

    public void addCommand(Command onComm,Command offComm){
        onCommandList.add(onComm);
        offCommandList.add(offComm);
    }

    public void onButtonWasPressed(int pos){
        if(pos < onCommandList.size() ){
            onCommandList.get(pos).execute();
            undoCmmand = onCommandList.get(pos);
        }else{
            System.out.println("pos out of on index");
        }
    }

    public void offButtonWasPressed(int pos){
        if(pos < offCommandList.size()){
            offCommandList.get(pos).execute();
            undoCmmand = offCommandList.get(pos);
        }else{
            System.out.println("pos out of off index");
        }
    }

    public void undoButtonPressed(){
        undoCmmand.undo();
    }

    @Override
    public String toString() {
        Iterator<Command> onIterator = onCommandList.iterator();
        Iterator<Command> offIterator = offCommandList.iterator();
        while(onIterator.hasNext()){
            System.out.println(onIterator.next().getClass().getName());
        }
        while(offIterator.hasNext()){
            System.out.println(offIterator.next().getClass().getName());
        }
        return super.toString();
    }

}

其次,添加一些可操控类

public class Stereo {
    int volume;
    public void on(){
        System.out.println("Stereo on");
    }

    public void off(){
        System.out.println("Stereo off");
    }

    public void setCD() {
        System.out.println("setCD");
    }

    public void setVolume(int volume) {
        System.out.println("setVolume "+volume);
        this.volume = volume;
    }

}

然后,修改命令类,添加undo方法

public interface Command {
    public void execute();
    public void undo();
}

再者,添加一些命令并实现undo

public class LightOffCommand implements Command{

    Light light;
    public LightOffCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.off();
    }
    public void undo() {
        System.out.println("undo light off");
        light.on();
    }

}
public class LightOnCommand implements Command{

    Light light;
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
    public void undo() {
        System.out.println("undo light on");
        light.off();
    }

}
public class StereoOffCommand implements Command{

    Stereo stereo;
    public StereoOffCommand(Stereo stereo) {
        this.stereo = stereo;
    }
    public void execute() {
        stereo.off();
    }
    public void undo() {
        System.out.println("undo stereo off");  
        stereo.on();
        stereo.setCD();
        stereo.setVolume(11);
    }
}
public class StereoOnCommand implements Command{

    Stereo stereo;
    public StereoOnCommand(Stereo stereo) {
        this.stereo = stereo;
    }
    public void execute() {
        stereo.on();
        stereo.setCD();
        stereo.setVolume(11);
    }
    public void undo() {
        System.out.println("undo stereo on");
        stereo.off();
    }

}

最后,修改测试类

public class Test {
    public static void main(String[] args) {
        SimpleRemoteControl control = new SimpleRemoteControl();
        Light light1 = new Light("厨房的白炽灯");
        Light light2 = new Light("卧室的小夜灯");
        Light light3 = new Light("客厅的水晶灯");
        Stereo stereo = new Stereo();
        Command commOn1 = new LightOnCommand(light1);
        Command commOn2 = new LightOnCommand(light2);
        Command commOn3 = new LightOnCommand(light3);
        Command commOff1 = new LightOffCommand(light1);
        Command commOff2 = new LightOffCommand(light2);
        Command commOff3 = new LightOffCommand(light3);
        Command commOn4 = new StereoOnCommand(stereo);
        Command commOff4 = new StereoOffCommand(stereo);
        control.addCommand(commOn1, commOff1);
        control.addCommand(commOn2, commOff2);
        control.addCommand(commOn3, commOff3);
        control.addCommand(commOn4, commOff4);
        control.toString();
        System.out.println("-----");
        control.onButtonWasPressed(0);
        control.onButtonWasPressed(1);
        control.onButtonWasPressed(2);
        control.onButtonWasPressed(3);
        control.onButtonWasPressed(11);
        control.offButtonWasPressed(0);
        control.undoButtonPressed();
        control.offButtonWasPressed(1);
        control.undoButtonPressed();
        control.offButtonWasPressed(2);
        control.undoButtonPressed();
        control.offButtonWasPressed(3);
        control.undoButtonPressed();
        control.offButtonWasPressed(14);
    }
}

升级版类图

这里写图片描述
忘记加undo方法了0.0
这里的undo并不完善,只记住了最后一步操作,这里可以将执行的操作放入栈中,执行undo时弹出。
测试结果:

com.demo.LightOnCommand
com.demo.LightOnCommand
com.demo.LightOnCommand
com.demo.StereoOnCommand
com.demo.LightOffCommand
com.demo.LightOffCommand
com.demo.LightOffCommand
com.demo.StereoOffCommand
-----
厨房的白炽灯 light on
卧室的小夜灯 light on
客厅的水晶灯 light on
Stereo on
setCD
setVolume 11
pos out of on index
厨房的白炽灯 light off
undo light off
厨房的白炽灯 light on
卧室的小夜灯 light off
undo light off
卧室的小夜灯 light on
客厅的水晶灯 light off
undo light off
客厅的水晶灯 light on
Stereo off
undo stereo off
Stereo on
setCD
setVolume 11
pos out of off index

命令模式的批处理

看名字好像听玄乎,其实就是一个命令其实执行了好几个操作,就像stereo的on方法其实执行好几个操作。
1.添加批处理命令

public class ServeralCommand implements Command{
    List<Command> commands;

    public ServeralCommand(List<Command> comms) {
        this.commands = comms;
    }

    public void execute() {
        Iterator<Command> iterator = commands.iterator();
        while(iterator.hasNext()){
            iterator.next().execute();
        }
    }

    public void undo() {
        Iterator<Command> iterator = commands.iterator();
        while(iterator.hasNext()){
            iterator.next().undo();
        }
    }

}

2.修改测试类

        SimpleRemoteControl control = new SimpleRemoteControl();
        Light light1 = new Light("厨房的白炽灯");
        Light light2 = new Light("卧室的小夜灯");
        Light light3 = new Light("客厅的水晶灯");
        Stereo stereo = new Stereo();
        Command commOn1 = new LightOnCommand(light1);
        Command commOn2 = new LightOnCommand(light2);
        Command commOn3 = new LightOnCommand(light3);
        Command commOff1 = new LightOffCommand(light1);
        Command commOff2 = new LightOffCommand(light2);
        Command commOff3 = new LightOffCommand(light3);
        Command commOn4 = new StereoOnCommand(stereo);
        Command commOff4 = new StereoOffCommand(stereo);

        ArrayList<Command> onComms = new ArrayList<Command>();
        onComms.add(commOn1);
        onComms.add(commOn2);
        onComms.add(commOn3);
        onComms.add(commOn4);
        ServeralCommand onComm = new ServeralCommand(onComms);
        ArrayList<Command> offComms = new ArrayList<Command>();
        offComms.add(commOff1);
        offComms.add(commOff2);
        offComms.add(commOff3);
        offComms.add(commOff4);
        ServeralCommand offComm = new ServeralCommand(offComms);
        control.addCommand(onComm, offComm);
        control.onButtonWasPressed(0);
        control.offButtonWasPressed(0);
        control.undoButtonPressed();

3.测试结果

厨房的白炽灯 light on
卧室的小夜灯 light on
客厅的水晶灯 light on
Stereo on
setCD
setVolume 11
厨房的白炽灯 light off
卧室的小夜灯 light off
客厅的水晶灯 light off
Stereo off
undo light off
厨房的白炽灯 light on
undo light off
卧室的小夜灯 light on
undo light off
客厅的水晶灯 light on
undo stereo off
Stereo on
setCD
setVolume 11

怎么样,一条命令执行了多个操作,很方便吧。

总结

本文要点:
极简命令模式
命令模式如何实现调用者和接收者的解耦
命令模式的撤销
命令模式的批处理命令

猜你喜欢

转载自blog.csdn.net/u011109881/article/details/81915188