命令模式

是什么?

先举个生活中的例子阐述命令模式。平时我们去银行办业务,快餐厅吃饭,有时因为人数多,资源有限等原因,我们必须排号,这个就是一个命令模式。 在这个例子里,由于我们的命令(办业务命令、点餐命令)不能马上执行,排号机接受了我们的命令,通过队列等,让我们的命令能保存(封装)下来,以便执行。

定义:一般“行为请求者”与“行为实现者”通常会紧密相连,有时我们需要把他们分离开实现一些功能,而命令模式则将“请求”封装成对象,实现了松耦合。

结构组成及作用

下图是对命令模式定义的uml: command uml diagram

画出类图一目了然,图中command将receiver的action封装起来,以供执行。

示例实现

示例代码模拟电灯开关。

public interface Command {
    void execute();
}

实际执行类

/**
 * receiver
 */
public class Light {
    public void turnOn() {
        System.out.println("turning on!!!");
    }

    public void turnOff() {
        System.out.println("turning off!!!");
    }
}
import java.util.Hashtable;
import java.util.Map;
import java.util.Objects;

//
// This is the invoker
//
public class Switch {
    private Map<String, Command> commandMap = new Hashtable<>();

    public void addCommand(final String key, final Command command) {
        commandMap.put(key, command);
    }

    public void executeCommand(String key) {
        Command c = commandMap.get(key);
        Objects.requireNonNull(c);
        c.execute();
    }

    public void executeAllCommands() {
        commandMap.values().stream().forEach(t -> t.execute());
    }

}
public class TurnOnCommand implements Command {
    private Light light;

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

    @Override
    public void execute() {
        light.turnOn();
    }
}
public class TurnOffCommand implements Command {
    private Light light;

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

    @Override
    public void execute() {
        light.turnOff();
    }
}
/**
    The client
 */
public class TestMain {
    public static void main(String[] args) {
        Switch mySwitch = new Switch();
        Light light = new Light();

        Command command1 = new TurnOnCommand(light);
        Command command2 = new TurnOffCommand(light);

        mySwitch.addCommand("turnOn", command1);
        mySwitch.addCommand("turnOff", command2);

        mySwitch.executeCommand("turnOn");
        mySwitch.executeCommand("turnOff");


    }

}

java8实现

@FunctionalInterface
public interface Command {
    void execute();
}
/**
 * receiver
 */
public class Light {
    public void turnOn() {
        System.out.println("turning on!!!");
    }

    public void turnOff() {
        System.out.println("turning off!!!");
    }
}
import java.util.Hashtable;
import java.util.Map;
import java.util.Objects;

//
// This is the invoker
//
public class Switch {
    private Map<String, Command> commandMap = new Hashtable<>();

    public void addCommand(final String key, final Command command) {
        commandMap.put(key, command);
    }

    public void executeCommand(String key) {
        Command c = commandMap.get(key);
        Objects.requireNonNull(c);
        c.execute();
    }

    public void executeAllCommands() {
        commandMap.values().stream().forEach(t -> t.execute());
    }

}
/**
    The client
 */
public class Java8TestMain {
    public static void main(String[] args) {
        Switch mySwitch = new Switch();
        Light light = new Light();

        Command command1 = new TurnOnCommand(light);
        Command command2 = new TurnOffCommand(light);

        mySwitch.addCommand("turnOn", () -> light.turnOn());
        mySwitch.addCommand("turnOff", () -> light.turnOff());

        mySwitch.executeCommand("turnOn");
        mySwitch.executeCommand("turnOff");

        mySwitch.executeAllCommands();

    }

}

完整代码么么哒

效果及应用场景

在下面的情况下可以考虑使用命令模式:

  1. 在不同时刻拍队列、执行请求。也就是说,当使用者希望封装起来的command对象可以与原始“请求”有一个无关的生存期时。
  2. 希望支持日志和系统恢复。
  3. 希望支持取消撤销操作。

references

results matching ""

    No results matching ""