在 Spring Boot 中,如何干掉 if else

程序员的成长之路

共 4111字,需浏览 9分钟

 · 2021-11-04

程序员的成长之路
互联网/程序员/技术/资料共享 
关注


阅读本文大概需要 5 分钟。

来自: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);

}//实现类1@Componentpublic 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())) { //促销订单处理 } //未来订单类型增加 }

}//实现类二@Componentpublic 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与实现类的映射关系 */@Componentpublic class HandlerProccessor implements BeanFactoryPostProcessor {    /**     * 扫描@OrderTypeHandlerAnno注解,初始化HandlerContext,将其注册到spring容器     *     * @param beanFactory bean工厂     * @throws BeansException     */    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {        Map 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 getBeansWithAnnotation(ConfigurableListableBeanFactory beanFactory, Class manager, Class annotation, String code) throws BeansException {        if (ObjectUtils.isEmpty(code)) {            throw new RuntimeException("code is null ");        }        Collection 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@Inheritedpublic @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浏览器测试结果)


如果类型不存在


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文档

"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.0modelVersion> <parent> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-parentartifactId> <version>2.2.1.RELEASEversion> <relativePath/> parent> <groupId>com.kayakgroupId> <artifactId>study-designartifactId> <version>0.0.1-SNAPSHOTversion> <name>study-designname> <description>Demo project for Spring Bootdescription>

<properties> <java.version>1.8java.version> properties>

<dependencies> <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency>

<dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-testartifactId> <scope>testscope> <exclusions> <exclusion> <groupId>org.junit.vintagegroupId> <artifactId>junit-vintage-engineartifactId> exclusion> exclusions> dependency> dependencies>

<build> <plugins> <plugin> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-maven-pluginartifactId> plugin> plugins> build>

project>

# 总结:


利用策略模式可以简化复杂的if else代码,方便维护,而利用自定义注解和自注册的方式,可以方便应对需求的变更。

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

这个就是个人笔记,不喜勿喷。

推荐阅读:

支付宝员工因绩效3.25B被辞退,员工告上法院,结果来了!

SQL去重的三种方法汇总

最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点个「在看」,点击上方小卡片,进入公众号后回复「面试题」领取,更多内容陆续奉上。

朕已阅 

浏览 12
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报