美文网首页
命令模式

命令模式

作者: Leocat | 来源:发表于2018-01-07 14:13 被阅读25次

    命令模式(Command Pattern)

    定义

    Encapsulate a request as an object,thereby letting you parameterize clients with different requests,queue or log requests,and support undoable operations.

    将请求封装成对象,让你可以使用不同的请求来参数化客户端,支持请求队列或者记录请求日志,并且可以支持可撤销的操作。

    类图定义如下:


    命令模式
    • Client(客户端)
      负责建立具体命令(ConcreteCommand)并组装接收者(Receiver)。

    • Command(命令)
      即需要执行的命令。

    • Receiver(接受者)
      负责执行命令的内容,业务代码在Receiver中实现。

    • Invoker(调用者)
      接收到命令,并执行命令。

    简单代码示例

    // 接收者
    public abstract class Receiver {
        // 业务逻辑在这里实现
        public abstract void doSomething();
    }
    
    public class ConcreteReceiver extends Receiver {
        public void doSomething() {
            // 具体业务的实现
        }
    }
    
    // 命令
    public abstract class Command {
        public abstract void execute();
    }
    
    public class ConcreteCommand extends Command{
    
        private Receiver receiver;
    
        public ConcreteCommand(Receiver receiver) {
            this.receiver = receiver;
        }
    
        public void execute() {
            receiver.doSomething();
        }
    }
    
    // 调用者
    public class Invoker {
        private Command command;//这里视情况用Command或者Queue<Command>等
    
        public Invoker(Command command) {
            this.command = command;
        }
    
        //执行命令
        public void action() {
            command.execute();
        }
    }
    
    // 客户端
    public class Client {
    
        public static void main(String[] args) {
    
            // 创建Receiver,组装Command
            Receiver receiver = new ConcreteReceiver();
            Command command = new ConcreteCommand(receiver);
    
            // 调用Invoker执行命令
            Invoker invoker = new Invoker(command);
            invoker.action();
        }
    }
    

    JDK中的Command Pattern

    JDK中的命令模式我们经常会用到,就是多线程中的Runnable。示例代码如下:

    public class JDKCommand {
    
        public static void main(String[] args) {
    
            Runnable runnable = new MyRunnable(); // Command
    
            Thread thread = new Thread(runnable);  // Invoker
    
            thread.start(); // 调用Invoker执行命令
        }
    
        public static class MyRunnable implements Runnable {
            public void run() {
                // Run
            }
        }
    }
    

    我们仔细看代码,发现Commandinvoker都有了,但是没有发现Receiver
    其实是因为我们在Commandrunnable)中把本应该由Receiver完成的业务逻辑给完成了,
    所以其实Receiver已经融入到Command中了。

    我们稍微变换一下,让Runnable符合我们上面的命令模式定义。示例如下:

    public class JDKCommand2 {
    
        public static void main(String[] args) {
    
            Receiver receiver = new ConcreteReceiver(); // Receiver
    
            Runnable runnable = new MyRunnable(receiver); // Command
    
            Thread thread = new Thread(runnable);  // Invoker
    
            thread.start(); // 调用Invoker执行命令
        }
    
        public static class MyRunnable implements Runnable {
    
            private Receiver receiver;
    
            public MyRunnable(Receiver receiver) {
                this.receiver = receiver;
            }
    
            public void run() {
                receiver.doSomething();
            }
        }
    
        interface Receiver {
            void doSomething();
        }
    
        public static class ConcreteReceiver implements Receiver {
            public void doSomething() {
                System.out.println("Receiver: do something");
            }
        }
    }
    

    命令模式的应用

    优点

    • 解耦

    调用者角色与接收者角色之间没有任何依赖关系,调用者实现功能时只需调用Command抽象类的execute方法就可以,不需要了解到底是哪个接收者执行。也就是解耦了命令的调用者和具体命令的执行者。

    • 可拓展

    Command的子类可以非常容易地扩展,而调用者Invoker和高层次的模块Client不产生严重的代码耦合。

    缺点

    类膨胀问题:N个命令就需要N个Command子类

    使用场景

    只要你认为是命令的地方就可以采用命令模式,例如,在GUI开发中,一个按钮的点击是一个命令,可以采用命令模式;触发-反馈机制的处理等。

    参考

    命令模式的定义

    相关文章

      网友评论

          本文标题:命令模式

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