Java设计模式 - 命令模式

定义

将一个请求或一个命令封装成一个对象,并定义命令的接收者和调用者,从而使得客户端参数化。

命令模式有三个比较重要的角色,分别是执行者 Invoker、接收者 Receiver 和命令 Command

命令模式的一个突出使用场景是在 GUI 中,比如编辑框的撤销、粘贴、剪切等操作。

所以,命令模式的主要应用于将被封装好的 Command 加入队列,并提供命令的执行、撤销、恢复等一系列操作。

其优点就是,能够对被执行的命令(Command)提供有效的管理,而且调用者(Invoker)和接收者(Receiver)之间不存在强耦合关系,使得三者之间能够充分解耦。

例子

简单利用一个关机、开机的例子,来说明命令模式的一般结构。我们定义一个调用者接口:

public interface Invoker {
    void request(int commandCode);
}

然后,定义接收者:

interface Receiver {
    void shutdown();
    void startup();
}

接下来是命令:

public interface Command {
    void execute();
}

定义一个开机命令,实现 Command 接口中的方法:

public class StartUpCmd implements Command {

    private Receiver receiver;

    public StartUpCmd(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        System.out.println("start up...");
    }
}

然后,定义一个关机的 Command:

public class ShutdownCmd implements Command {

    private Receiver receiver;

    public ShutdownCmd(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    public void execute() {
        receiver.shutdown();
    }
}

然后,定义一个接收者计算机,用于接收命令,接收者是真正去执行某些操作的角色,而 Command 仅仅是一个命令,不提供具体 Action:

public class ComputerReceiver implements Receiver {

    @Override
    public void shutdown() {
        System.out.println("shutdown...");
    }

    @Override
    public void startup() {
        System.out.println("start up...");
    }
}

下面,看看具体命令调用者的处理:

public class CPUInvoker implements Invoker {

    private HashMap commandMap;

    public CPUInvoker() {
        commandMap = new HashMap<>();
    }

    @Override
    public void request(int commandCode) {
        Command c = commandMap.get(commandCode);
        if (c != null) {
            c.execute();
        }
    }

    public void registerCommand(int code, Command command) {
        commandMap.put(code, command);
    }
}

调用者仅仅发起了某个命令的请求,并能够对每个命令进行管理,比如添加、移除等行为。

定义客户端:

public class Client {
    public static void main(String[] args) {
        ComputerReceiver computer = new ComputerReceiver();

        Command shutdown = new ShutdownCmd(computer);
        Command startup = new StartUpCmd(computer);

        CPUInvoker cpu = new CPUInvoker();
        cpu.registerCommand(0x01, shutdown);
        cpu.registerCommand(0x02, startup);
        cpu.request(0x01);

    }
}

从中可以看出,客户端将被封装好的命令参数化,并传给了调用者 CPUInvoker,而真正执行 Action 的 ComputerReceiver 与 命令的调用者 CPUInvoker 之间不存在过强的耦合关系。

除此之外,能够更好地对命令进行管理。

总结

命令模式是行为型设计模式之一,其优点和使用场景显而易见,并不难理解。

但是,命令模式的缺点几乎是所有设计模式的通病,也就是大量衍生类的创建,在实际项目中使用命令模式还需要斟酌。

总之,命令模式给我们提供的好处非常多,更强的灵活性,更好的扩展性,等等。在开发中,可以适当地变通,基于命令模式的前提下,减少不必要的类的创建,又能体验命令模式给我们带来的好处。

本文由Fynn_原创,未经许可,不得转载!

你可能感兴趣的:(Java设计模式 - 命令模式)