zoukankan      html  css  js  c++  java
  • 【转】消除代码中的 if-else/switch-case

      在很多时候,我们代码中会有很多分支,而且分支下面的代码又有一些复杂的逻辑,相信很多人都喜欢用 if-else/switch-case 去实现。做的不好的会直接把实现的代码放在 if-else/switch-case 的分支之下:

    switch ( type ) {
        case case1:
            ...
            ...
            break;
        case case2:
            ...
            ...
            break;
        case case3:
            ...
            ...
            break
        default:
            return null;
    }
    

     这样的代码不仅冗长,读起来也非常困难。做的好一点的会把这些逻辑封装成函数然后在分支中调用:

    switch ( type ) {
        case case1:
            return case1Func();
        case case2:
            return case2Func();
        case case3:
            return case3Func();
        default:
            return null;
    }
    
    即使这样也是面向过程思维的写法,以前写 C 程序的时候也总喜欢这样写,毫无设计模式可言。不仅违背开闭原则,而且随着 switch-case 分支的增多,该段代码只会越来越冗长。其实这种代码已经有成熟的模式去消除诸多的 if-else/switch-case 分支。本文就教大家在 Spring 中如何用注解+策略模式+简单工厂的方式消除 if-else/switch-case 。我们就拿 QQ 空间的个人中心举例子,假如 QQ 空间个人中心有四个 tab 分别是列出我的说说、我的日志、我的照片和我的访客。一般的后台代码很有可能如下:
     
    //各个 tab 名称的枚举:
    public enum UserRelatedType {
        /**
         * 说说
         */
        SHUOSHUO("说说"),
    
        /**
         * 日志
         */
        RIZHI("日志"),
    
        /**
         * 发布
         */
        ZHAOPIAN("照片"),
    
        /**
         * 访客
         */
        FANGKE("");
    
        private String desc;
    
        UserRelatedType(String desc) {
            this.desc = desc;
        }
    
        public String getDesc() {
            return desc;
        }
    
        public void setDesc(String desc) {
            this.desc = desc;
        }
    }
    

    列出 QQ 用户个人中心相关 tab 的代码:

    public List<UserRelatedVO> listRelated(UserRelatedQuery query){
    
        UserRelatedType relatedType = UserRelatedType.valueOf(StringUtils.upperCase(query.getType()) );
        switch ( relatedType ) {
            case SHUOSHUO:
                return listRelatedShuoshuo( query );
            case RIZHI:
                return listRelatedRizhi( query );
            case ZHAOPIAN:
                return listRelatedZhaopian( query );
            case FANGKE:
                return listRelatedFangke( query );
            default:
                return null;
        }
    }
    

     而采用注解+策略模式+简单工厂,重构后代码如下:

    • 1、定义一个注解,用来完全消除 if-else:
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface RelatedTypeAnnotation {
        /**
         * 用户相关类型名称
         */
        UserRelatedType value();
    }
    
    • 2、先定义了个接口,所有 tab 都要实现该接口。其中 list 是 tab 数据展示的方法。
    public interface UserRelated {
    
        /**
         * 列出详细信息
         *
         * @param query
         * @return
         */
        List<UserRelatedVO> list(UserRelatedQuery query);
    }
    
    •  3、定义具体的各个 tab 的实现,继承 UserRelated 策略接口

       我的说说

    @Component("userRelatedShuoshuo")
    @RelatedTypeAnnotation( value = UserRelatedType.SHUOSHUO )
    public class UserRelatedShuoshuo implements UserRelated {
        @Override
        public List<UserRelatedVO> list(UserRelatedQuery query) {
            System.out.println("我的说说!");
            return list;
        }
    }
    

     我的日志

    @Component("userRelatedRizhi")
    @RelatedTypeAnnotation( value = UserRelatedType.RIZHI )
    public class UserRelatedRizhi implements UserRelated {
        @Override
        public List<UserRelatedVO> list(UserRelatedQuery query) {
            System.out.println("我的日志!");
            return list;
        }
    }
    

     我的照片

    @Component("userRelatedZhaopian")
    @RelatedTypeAnnotation( value = UserRelatedType.ZHAOPIAN )
    public class UserRelatedZhaopian implements UserRelated {
        @Override
        public List<UserRelatedVO> list(UserRelatedQuery query) {
            System.out.println("我的照片!");
            return list;
        }
    }
    

     我的访客

    @Component("userRelatedFangke")
    @RelatedTypeAnnotation( value = UserRelatedType.FANGKE )
    public class UserRelatedFangke implements UserRelated {
        @Override
        public List<UserRelatedVO> list(UserRelatedQuery query) {
            System.out.println("我的访客!");
            return list;
        }
    }
    
    •  3、定义一个从 Spring context 获取 bean 的工具类
    @Component
    public class SpringContextUtil implements ApplicationContextAware {
    
        private ApplicationContext context;
    
        public ApplicationContext getContext() {
            return context;
        }
    
        @Override
        public void setApplicationContext(ApplicationContext context)throws BeansException {
            this.context = context;
        }
    }
    
    •  4、定义一个简单工厂,用来生产各种 tab 对象。
    @Component
    public class UserRelatedFactory {
    
        @Autowired
        SpringContextUtil springContextUtil;
        
        private static Map<UserRelatedType, UserRelated> userRelatedMap = Maps.newConcurrentMap();
    
        //工厂将 Spring 装配的相关的 Bean 用 Map 保存起来
        public UserRelatedFactory(){
            Map<String, Object> beanMap = springContextUtil.getContext().getBeansWithAnnotation(RelatedTypeAnnotation.class);
    
            for(Object userRelated : beanMap.values()) {
                RelatedTypeAnnotation annotation = userRelated.getClass().getAnnotation(RelatedTypeAnnotation.class);
                userRelatedMap.put(annotation.value(), (UserRelated)userRelated);
            }
        }
    
        public static UserRelated createRelated(UserRelatedType relatedType) {
            return userRelatedMap.get( relatedType );
        }
    }
    

     5、调用的代码(listRelated 会在 controller 中被调用)。

    public List<UserRelatedVO> listRelated(UserRelatedQuery query){
    
        UserRelatedType relatedType = UserRelatedType.valueOf(StringUtils.upperCase(query.getType()) );
        UserRelated related = UserRelatedFactory.createRelated( relatedType );
        if( related != null ) {
            return related.list( query );
        } else {
            return null;
        }
    }
    

     重构后的代码如果需要再新增一种 tab,比如我的好友,只需要新增一种类型继承 UserRelated 实现其中的 list,并加上相应的注解即可。

    作者:水目沾
    链接:https://juejin.im/post/5ca9f113e51d452b5e458ec3
    来源:掘金

  • 相关阅读:
    iOS学习笔记(六)——ViewController
    IOS学习笔记(五)——UI基础UIWindow、UIView
    iOS学习笔记(四)——iOS应用程序生命周期
    iOS学习笔记(三)——iOS系统架构
    iOS学习笔记(二)——Hello iOS
    iOS学习笔记(一)——ios搭建开发环境
    Android UI开发第三十篇——使用Fragment构建灵活的桌面
    android实现卸载提示
    Android UI开发第二十六篇——Fragment间的通信
    Android UI开发第二十九篇——Android中五种常用的menu(菜单)
  • 原文地址:https://www.cnblogs.com/zdd-java/p/10720984.html
Copyright © 2011-2022 走看看