在 Spring Boot 中,如何干掉 if else
正文如下
来源:https://blog.csdn.net/hncu1306602liuqiang
看到crossover Jie的文章《利用策略模式优化过多if else 代码》后受到启发,可以利用策略模式简化过多的if else代码。
# 需求
这里虚拟一个业务需求,让大家容易理解。假设有一个订单系统,里面的一个概念是根据订单的不同类型做出不同的处理。
# 项目结构
订单实体
/** * 订单实体 */public class OrderDTO { private String code; private BigDecimal price;
/* * 订单类型: * 1:普通订单 * 2:团购订单 * 3:促销订单 */ private String type;//getter,setter自己实现}service接口
/** * 订单处理 */public interface IOrderService {
/** * 根据订单的不同类型做出不同的处理 * * @param dto 订单实体 * @return 为了简单,返回字符串 */ String orderHandler(OrderDTO dto);
}//实现类1public class OrderServiceImpl implements IOrderService {
public String orderHandler(OrderDTO dto) { if ("1".equals(dto.getType())) { //普通订单处理 } else if ("2".equals(dto.getType())) { //团购订单处理 } else if ("3".equals(dto.getType())) { //促销订单处理 } //未来订单类型增加 }
}//实现类二public class OrderServiceImpl implements IOrderService { //使用策略模式实现 private HandlerContext handlerContext;
public String orderHandler(OrderDTO dto) { /* * 1:使用if..else实现 * 2:使用策略模式实现 */ AOrderTypeHandler instance = handlerContext.getInstance(dto.getType()); return instance.handler(dto); }
}利用策略模式只需要2行代码就可以搞定(也可以用工厂)
HandlerContext和HandlerProccessor
/** * 订单策略模式环境 * 这个类的注入由HandlerProccessor实现 */public class HandlerContext { private Map<String, AOrderTypeHandler> handlerMap;
/** * 构造传参不能直接使用注解扫入 */ public HandlerContext(Map<String, AOrderTypeHandler> handlerMap) { this.handlerMap = handlerMap; }
/** * 获得实例 * * @param type * @return */ public AOrderTypeHandler getInstance(String type) { if (type == null) { throw new IllegalArgumentException("type参数不能为空"); } AOrderTypeHandler clazz = handlerMap.get(type); if (clazz == null) { throw new IllegalArgumentException("该类型没有在枚举OrderTypeHandlerAnno中定义,请定义:" + type); } return clazz; }
}/** * 策略模式,处理type与实现类的映射关系 */public class HandlerProccessor implements BeanFactoryPostProcessor {
/** * 扫描@OrderTypeHandlerAnno注解,初始化HandlerContext,将其注册到spring容器 * * @param beanFactory bean工厂 * @throws BeansException */ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { Map<String, AOrderTypeHandler> handlerMap = new HashMap<>(); for (OrderTypeEnum temp : OrderTypeEnum.values()) { AOrderTypeHandler beanInstacle = getBeansWithAnnotation(beanFactory, AOrderTypeHandler.class, OrderTypeHandlerAnno.class, temp.getCode()); handlerMap.put(temp.getCode(), beanInstacle); } HandlerContext context = new HandlerContext(handlerMap); //单例注入 beanFactory.registerSingleton(HandlerContext.class.getName(), context); }
/* * 通过父类+注解找到实体类 */ private <T> T getBeansWithAnnotation(ConfigurableListableBeanFactory beanFactory, Class<T> manager, Class<? extends OrderTypeHandlerAnno> annotation, String code) throws BeansException { if (ObjectUtils.isEmpty(code)) { throw new RuntimeException("code is null "); } Collection<T> tCollection = beanFactory.getBeansOfType(manager).values(); for (T t : tCollection) { OrderTypeHandlerAnno orderTypeHandlerAnno = t.getClass().getAnnotation(annotation); if (ObjectUtils.isEmpty(orderTypeHandlerAnno)) { throw new RuntimeException("该注解没有写入值 :" + code); } //注解值是否与code相等 if (code.equals(orderTypeHandlerAnno.value().getCode())) { return t; } } throw new RuntimeException("通过code没有找到该注解对应的实体类 :" + code); }
}父抽象类+注解+枚举
/** * 订单类型处理定义 * 使用抽象类,那么子类就只有一个继承了 */public abstract class AOrderTypeHandler {
/** * 一个订单类型做一件事 * * @param dto 订单实体 * @return 为了简单,返回字符串 */ abstract public String handler(OrderDTO dto);
}
/** * 订单类型注解 * 使用方式: * 1:普通订单 @OrderTypeHandlerAnno("1") * 2:团购订单 @OrderTypeHandlerAnno("2") * 3:促销订单 @OrderTypeHandlerAnno("3") */({ElementType.TYPE})(RetentionPolicy.RUNTIME)public OrderTypeHandlerAnno {
OrderTypeEnum value();
}
/** * 订单类型枚举 */public enum OrderTypeEnum { Normal("1", "普通"), Group("2", "团队"), Promotion("3", "促销");
private String code; //代码 private String name; //名称,描述
OrderTypeEnum(String code, String name) { this.code = code; this.name = name; }
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
/** * 根据code属性获取name属性 * * @param code * @return */ public static String getNameByCode(String code) { for (OrderTypeEnum temp : OrderTypeEnum.values()) { if (temp.getCode().equals(code)) { return temp.getName(); } } return null; }
}业务人员实现类
//业务代码/** * 普通订单处理 */(OrderTypeEnum.Normal)public class NormalOrderHandler extends AOrderTypeHandler {
public String handler(OrderDTO dto) { return "处理普通订单"; }
}
/** * 团队订单处理 */(OrderTypeEnum.Group)public class GroupOrderHandler extends AOrderTypeHandler {
public String handler(OrderDTO dto) { return "处理团队订单"; }
}
/** * 促销订单处理 */(OrderTypeEnum.Promotion)public class PromotionOrderHandler extends AOrderTypeHandler {
public String handler(OrderDTO dto) { return "处理促销订单"; }
}测试结果(使用chrome浏览器测试结果)
如果类型不存在
controller
/** * 策略模式 */@RestControllerpublic class StrategyController { @Resource(name = "orderServiceImpl") private IOrderService orderService;
@GetMapping("/api/order") @ResponseBody public String orderSave(OrderDTO dto) { String str = orderService.orderHandler(dto); return "{\"status\":1,\"msg\":\"保存成功\",\"data\":\"" + str + "\"}"; }
}pom.xml文档
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.kayak</groupId> <artifactId>study-design</artifactId> <version>0.0.1-SNAPSHOT</version> <name>study-design</name> <description>Demo project for Spring Boot</description>
<properties> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
</project># 总结:
利用策略模式可以简化复杂的if else代码,方便维护,而利用自定义注解和自注册的方式,可以方便应对需求的变更。
主要是方便了业务人员编写代码。
相关文章