美文网首页
命令模式 -- 实践

命令模式 -- 实践

作者: 东南枝下 | 来源:发表于2021-02-02 17:50 被阅读0次

    学习命令模式后,使用命令模式对项目中switch做一些优化
    在重构一书Switch Statements(switch惊悚现身)这一节中也阐述了重构switch的理由
    使用命令模式来重构,本质上是使用多态来取代switch

    原代码如下:

        switch (fieldType) {
                case enum1:
                    doSomething(parameter);
                    break;
                case enum2:
                         ...
                    break;
                         ...
                default:
                    break;
            }
    

    原本的代码根据fieldType值的不同执行不同的逻辑,而这个fieldType来源于一个注解的参数

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    public @interface Annotation {
        /**
         * 根据不同的类别选择不同的处理方式
         *
         * @return 类别枚举
         */
        FieldType fieldType();
        ...
    }
    

    FieldType 则是一个枚举类

    public enum FieldType {
      ...
    }
    
    

    重构方式如下:

    1. 接收者:这里将具体的业务逻辑执行类看作接收者,原本的代码已经可以复用,不做特别的关注

    2. 命令角色

    /**
     * 命令抽象接口
     *
     * @author Jenson
     */
    public interface Command {
    
        /**
         * 设置参数
         *
         * @param parameter 参数
         */
        void setParameter(Parameter parameter);
    
        /**
         * 执行命令
         */
        void execute();
    }
    
    1. 具体的命令
    /**
     * @author Jenson
     */
    @Component
    public class DoSomethingCommand implements Command {
    
        private Parameter parameter;
    
        @Override
        public void setParameter(Parameter parameter) {
            this.parameter = parameter;
        }
    
        @Override
        public void execute() {
            doSomething(parameter);
        }
    }
    
    

    具体的命令实现命令接口,在这里完成原本应该在case中完成的工作,每一个case对应一个具体的命令实现。这样即使以后需要增加别的情况,也只需要增加命令实现类就好了,无需再去动、去阅读研究以前的代码。撒花~

    1. 调用者
      这里做的比较简单就是个没得感情的调用机器
    /**
     * 调用者抽象角色
     *
     * @author Jenson
     */
    public interface Invoker {
        /**
         * 执行命令
         *
         * @param command 命令
         */
        void action(Command command);
    }
    
    
    /**
     * @author Jenson
     */
    @Component
    public class InvokerImpl implements Invoker {
    
        @Override
        public void action(Command command) {
            command.execute();
        }
    }
    
    1. 重构原代码
            Invoker invoker = SpringContextUtil.getBean(InvokerImpl.class);
            Command command = (Command) SpringContextUtil.getBean(concreteCommand);
            command.setParameter(currentTenantId, fieldValueList, valueMap);
            invoker.action(command);
    // --------------原代码对比如下----------------
    //      switch (fieldType) {
    //          case enum1:
    //              doSomething(parameter);
    //              break;
    //          case enum2:
    //                     ...
    //              break;
    //                     ...
    //          default:
    //              break;
    //      }
    

    上述代码将fieldType替换为concreteCommand,concreteCommand是具体的命令实现类,
    此处修改了注解的传入参数

    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    public @interface Annotation {
        /**
         * 选择不同的命令来处理
         *
         * @return 命令类
         */
        Class concreteCommand();
    
    // --------------原代码对比如下----------------
    //      /**
    //       * 根据不同的类别选择不同的处理方式
    //       *
    //       * @return 类别枚举
    //       */
    //      FieldType fieldType();
    //      ...
    }
    

    类图如下:

    图片.png

    后记:虽说是命令模式,但从使用的结果来看,却是策略模式

    相关文章

      网友评论

          本文标题:命令模式 -- 实践

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