zoukankan      html  css  js  c++  java
  • 命令模式/command模式/行为型模式

    举个栗子

    指挥官向士兵下达命令,士兵执行

    实现代码如下:

    class Soldier {
        public void exe() {
            System.out.println("执行命令");
        }
    }
    
    class Commander {
        public void invok() {
            Soldier soldier=new Soldier();
            soldier.exe();
        }
    }
    

    代码问题

    上诉代码是最基本的一个实现,存在问题:

    1. Commander和Soldier高度耦合
    2. 新增命令的话,要改动Commander类,扩展性不好(影响已有实现),不符合OCP原则
    3. 指挥官指挥实现多条命令时,又要改Commander
    4. 士兵执行命令时如果加一些控制的话,如记录日志、延缓执行,加到哪都不合适,SRP和OCP原则。

    重构后代码

    class Soldier {
        public void doCommandA() {
            System.out.println("执行命令A");
        }
        public void doCommandB() {
            System.out.println("执行命令B");
        }
    }
    
    class CommandCenterA implements Command{
        Soldier soldier;
        public CommandCenterA(Soldier soldier) {
            this.soldier=soldier;
        }
        
        @Override
        public void exe() {
            waitTime();
            soldier.doCommandA();
            soldier.doCommandB();
        }
        private void waitTime() {
            System.out.println("延迟执行");
        }
        
    }
    
    class Commander {
        Command command;
        public Commander(Command command) {
            this.command=command;
        }
        public void exe(){
            command.exe();
        }
    }
    
    class Client{
    public static void main(String[] args) {
        Soldier soldier=new Soldier();
        Command command=new CommandCenterA(soldier);//将soldier注入到命令中心
        Commander commander=new Commander(command);//将命令中心注入到指挥官
        commander.exe();
    }
    

    解决的问题

    1. Commander和Soldier隔离,解除耦合,
    2. 新增命令时,只需新增Command接口的实现CommandCenter,实现对命令和请求控制
    3. CommandCenter可以实现复合命令,延迟执行,记录日志等

    命令模式

    命令模式把一个请求或者操作封装到一个对象中,并把发出命令和执行命令隔离,使得发出命令不必关心命令如何执行。

    讲个实例:
    比如开关灯和开关空调。
    最原始的,就是把两根电线连到一起,灯亮空调开,断开,灯灭空调关。(Receiver)
    现在我们加了个开关,开关不仅能开灯,还能开空调。(将电灯开关和空调开关进一步抽象)
    开关内部的实现,就是我们的命令中心。(开空调时可以设置温度,开灯时可以延缓执行)
    将开关和电线隔离,并加入了我们对命令的具体控制。这就是命令模式。

    Java实现要点 Invoker(请求者)+Commander(命令中心)+Receiver(执行者)

    1. 将请求者和执行者,加入中间层“命令中心”,将请求者对象绑定于一个动作
    2. 将命令中心抽象出接口,使得请求者依赖于接口而不是具体实现
    3. 命令中心实现对请求者和执行者的解耦

    JDK中的命令模式

    比较经典的应该就是Runnable了吧。

    //执行者
    Runnable soldier= new Runnable() {
        public void run() {
            System.out.println("执行命令");
        }
    };
    
    //命令中心
    Runnable thread=new Thread(solder);//可继承Thread继续定制
    thread.sleep(1000);
    
    //请求者
    thread.start();
    

    Thread源码:

    /* What will be run. */
    private Runnable target;
    
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
    
    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
    

    注入了Runnable,并实现了对Runnable的控制。

    优点

    1. 松耦合
    2. “命令中心”对命令可控(如日志化,延缓,复合命令),对请求可控(如队列,参数化)
    3. 扩展性。只需要实现新的“命令中心”即可,任意装配,并且不影响已有的实现,因为命令发起者(指挥官)中的命令中心时接口注入。



    I am a slow walker, but I never walk backwards.



  • 相关阅读:
    EP-N8530S USB WIFI 驱动移植
    MySQL(十三)事务处理和字符集
    MySQL(十二)游标和触发器
    《Google软件测试之道》测试工程师
    jmeter(十二)关联之正则表达式提取器
    MySQL(十一)视图及存储过程
    jmeter(十一)JDBC Request之Query Type
    MySQL(十)操纵表及全文本搜索
    MySQL(九)插入、更新和删除
    MySQL(八)子查询和分组查询
  • 原文地址:https://www.cnblogs.com/lknny/p/5779475.html
Copyright © 2011-2022 走看看