尽可能的“消除”代码中繁琐的if..else
当我们写代码时,肯定会碰到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
整体思路如下:
- 统一处理接口
- 自定义注解
- 利用spring扫描自定义注解,生成具体的策略模式所需上下文,并注册到spring容器中
- 具体处理类实现
一、统一处理接口
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
上一篇: 数据结构算法--单词接龙(C++)
下一篇: Ansible Jinja2 模板使用