Java设计模式 - 命令模式

作者: a57ecf3aaaf2 | 来源:发表于2017-11-18 13:44 被阅读13次

    定义

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

    命令模式有三个比较重要的角色,分别是执行者 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<Integer, Command> 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设计模式 - 命令模式

        本文链接:https://www.haomeiwen.com/subject/ozeevxtx.html