新知一下
海量新知
6 0 8 7 8 8 4

在 Spring Boot 中,如何干掉 if else

java数据修炼之道 | 学习改变人生, 技术成就未来 2021/12/01 21:37

看到crossover Jie的文章《利用策略模式优化过多if else 代码》后受到启发,可以利用策略模式简化过多的if else代码。

# 需求

这里虚拟一个业务需求,让大家容易理解。假设有一个订单系统,里面的一个概念是根据订单的不同类型做出不同的处理。

# 项目结构

新知达人, 在 Spring Boot 中,如何干掉 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);

}

//实现类1

@Component

public class OrderServiceImpl implements IOrderService {

@Override

public String orderHandler(OrderDTO dto) {

if ("1".equals(dto.getType())) {

//普通订单处理

} else if ("2".equals(dto.getType())) {

//团购订单处理

} else if ("3".equals(dto.getType())) {

//促销订单处理

}

//未来订单类型增加

}

}

//实现类二

@Component

public class OrderServiceImpl implements IOrderService {

//使用策略模式实现

@Autowired

private HandlerContext handlerContext;

@Override

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与实现类的映射关系

*/

@Component

public class HandlerProccessor implements BeanFactoryPostProcessor {

/**

* 扫描@OrderTypeHandlerAnno注解,初始化HandlerContext,将其注册到spring容器

*

* @param beanFactory bean工厂

* @throws BeansException

*/

@Override

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")

*/

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

public @interface 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;

}

}

业务人员实现类

//业务代码

/**

* 普通订单处理

*/

@Component

@OrderTypeHandlerAnno(OrderTypeEnum.Normal)

public class NormalOrderHandler extends AOrderTypeHandler {

@Override

public String handler(OrderDTO dto) {

return "处理普通订单";

}

}

/**

* 团队订单处理

*/

@Component

@OrderTypeHandlerAnno(OrderTypeEnum.Group)

public class GroupOrderHandler extends AOrderTypeHandler {

@Override

public String handler(OrderDTO dto) {

return "处理团队订单";

}

}

/**

* 促销订单处理

*/

@Component

@OrderTypeHandlerAnno(OrderTypeEnum.Promotion)

public class PromotionOrderHandler extends AOrderTypeHandler {

@Override

public String handler(OrderDTO dto) {

return "处理促销订单";

}

}

测试结果(使用chrome浏览器测试结果)

新知达人, 在 Spring Boot 中,如何干掉 if else

新知达人, 在 Spring Boot 中,如何干掉 if else

新知达人, 在 Spring Boot 中,如何干掉 if else

如果类型不存在

新知达人, 在 Spring Boot 中,如何干掉 if else

controller

/**

* 策略模式

*/

@RestController

public 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代码,方便维护,而利用自定义注解和自注册的方式,可以方便应对需求的变更。

主要是方便了业务人员编写代码。


更多“Spring”相关内容

更多“Spring”相关内容

新知精选

更多新知精选