欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

尽可能的“消除”代码中繁琐的if..else

程序员文章站 2022-06-28 18:42:56
当我们写代码时,肯定会碰到if...else语句,但是过多的if...else语句会让代码可读性变差,也不利于扩展,虽然自己写代码一时爽,若是交由别人维护,不免就会喷嚏连天,平时呢代码中的if...else语句大多数长这样public String handleOrder(OrderDto dto) { if("团购".equals(dto.getType())) { return "处理团购订单"; }else if("单点".equals......

当我们写代码时,肯定会碰到if...else语句,但是过多的if...else语句会让代码可读性变差,也不利于扩展,虽然自己写代码一时爽,若是交由别人维护,不免就会喷嚏连天,平时呢代码中的if...else语句大多数长这样

public String handleOrder(OrderDto dto) {
         if("团购".equals(dto.getType())) {
             return "处理团购订单";
         }else if("单点".equals(dto.getType())) {
             return "处理单点订单";
         }else if("外卖".equals(dto.getType())) {
             return "处理外卖订单";
         }else {
             return null;
         }
    }

比如根据订单的类型,选择怎么处理订单,这是传统实现,那么今天给大家带来用策略模式“消除”if...else

整体思路如下:

  1. 统一处理接口
  2. 自定义注解
  3. 利用spring扫描自定义注解,生成具体的策略模式所需上下文,并注册到spring容器中
  4. 具体处理类实现

一、统一处理接口

1、将所有的处理类抽象出来

public abstract class AbstractHandler {

        abstract public String handle(); 

}

2、每个选择项实现具体的处理方法handle

@Component
       @HandlerType("201")

public class TuanGouHandler extends AbstractHandler{

       @Override

       public String handle(){

       //具体业务逻辑实现

       }

}

有多少个选择项,就实现多少个AbstractHandler,并且每个实现类都必须注册到spring容器中,所以用@Component注解,@HandlerType("201")注解用来标识是哪个处理类

二、自定义注解

1、自定义注解

     @Target(ElementType.TYPE)
            @Retention(RetentionPolicy.RUNTIME)
            @Documented
            @Inherited
            public @interface HandlerType {
                   String value();
             }

三、利用spring扫描自定义注解,生成具体的策略模式所需上下文,并注册到spring容器中

@Component
public class HandlerProcessor implements BeanFactoryPostProcessor {

@SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Map<String, Class> map = new HashMap<String, Class>();
        //classScanner是一个工具类,用来扫描所有在包下注解的实现
        //具体是用来扫描带注解HandlerType的处理类
        //将处理类注解HandlerType的value作为map的key,具体的Class作为value
        //handlerContext.getInstance()方法则会返回具体的处理类
        ClassScanner classScanner = new DefaultClassScanner();
        classScanner.scanByAnno(Arrays.asList("具体包名"), HandlerType.class).forEach(
                aClass -> {
                    //获取注解的value值,放入map

                   //上文的201作为key,value则为TuanGouHandler.class,绑定type的具体实现类
                    String value = ((HandlerType) aClass.getAnnotation(HandlerType.class)).value();
                    map.put(value, aClass);
                }
        );
        HandlerContext handlerContext = new HandlerContext(map);
        //注册handlerContext到spring容器,autowired才会有效果
        beanFactory.registerSingleton(handlerContext.getClass().getName(), handlerContext);
    }

}

ClassScanner是一个开源的工具类,如何获取请看这里 https://blog.csdn.net/weixin_34218890/article/details/92044693

HandlerContext 则存储相应的type和class

@SuppressWarnings({"rawtypes"})
public class HandlerContext {
    private Map<String, Class> handlerMap = new HashMap<String, Class>();
    
    public HandlerContext(Map<String, Class> handlerMap) {
        this.handlerMap = handlerMap;
    }
    
    public AbstractHandler getInstance(String type) {
        Class class1 = handlerMap.get(type);
        return (AbstractHandler) BeanUtil.getBean(class1);
    }
}

BeanUtil是一个通过className获取在spring中的bean工具类

@Component
@SuppressWarnings({"unchecked", "static-access", "rawtypes"})
public class BeanUtil implements BeanFactoryAware {
    
    private static BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
    
    public static Object getBean(Class className) {
        return beanFactory.getBean(className);
    }

}

HandlerProcessor 和 BeanUtil 一定要加上注解@Component,才会被spring扫描到

OK,接下来再你的service加上以下两句代码就搞掂了

    @Autowired
    HandlerContext handlerContext;

    public String handleOrder(OrderDto dto) {

         AbstractHandler handler = handlerContext.getInstance(dto.getType());
         return handler.handle(dto).
    }

整个思路就是用spring的钩子功能,BeanFactoryPostProcessor 是spring在容器初始化时对外暴露的扩展点,也就是说我们可以通过重写postProcessBeanFactory方法,实现我们自己所需要的功能,并可以在spring里初始化一些我们自己的东西,最终通过map将type与具体的处理类关联起来,每个处理类的HandlerType不一样,于是处理方法也就变得具体化了

 

 

本文地址:https://blog.csdn.net/Home_Bro123/article/details/107340102