SpringBoot如何干掉if else?

4 篇文章 0 订阅
2 篇文章 0 订阅

前言

看到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
@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浏览器测试结果)

如果类型不存在

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

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

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

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当使用 Spring Boot 和 Redis 实现分布式锁时,可以通过以下步骤来编写代码: 1. 配置 Redis: 首先,确保在 Spring Boot 项目的配置文件(如 application.properties 或 application.yml)中配置 Redis。例如: ``` spring.redis.host=localhost spring.redis.port=6379 ``` 2. 添加 RedisTemplate Bean: 在 Spring Boot 项目的配置类中,添加 RedisTemplate Bean。这个 Bean 可以用于执行 Redis 操作。例如: ```java @Configuration public class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); // 设置序列化器,可以根据需要选择不同的序列化器 redisTemplate.setDefaultSerializer(new StringRedisSerializer()); return redisTemplate; } } ``` 3. 创建分布式锁类: 编写一个分布式锁类,例如 `DistributedLock`。这个类将使用 RedisTemplate 来实现分布式锁的获取和释放。以下是一个简单的示例: ```java @Component public class DistributedLock { private static final String LOCK_PREFIX = "lock:"; private static final long DEFAULT_EXPIRE_TIME = 30000; // 默认锁过期时间为30秒 private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS; @Autowired private RedisTemplate<String, Object> redisTemplate; public boolean acquireLock(String lockKey) { String key = LOCK_PREFIX + lockKey; return redisTemplate.opsForValue().setIfAbsent(key, true, DEFAULT_EXPIRE_TIME, DEFAULT_TIME_UNIT); } public void releaseLock(String lockKey) { String key = LOCK_PREFIX + lockKey; redisTemplate.delete(key); } } ``` 4. 使用分布式锁: 在需要加锁的地方,使用 `DistributedLock` 类的 `acquireLock` 方法来获取锁。例如: ```java @Service public class MyService { @Autowired private DistributedLock distributedLock; public void doSomething() { String lockKey = "myLock"; boolean acquired = distributedLock.acquireLock(lockKey); try { if (acquired) { // 执行需要加锁的操作 } else { // 获取锁失败,处理逻辑 } } finally { distributedLock.releaseLock(lockKey); } } } ``` 以上代码演示了如何使用 Spring Boot 和 Redis 实现简单的分布式锁。在 `doSomething` 方法中,先尝试获取锁,如果成功获取到锁就执行需要加锁的操作,然后释放锁。如果获取锁失败,则根据实际需求进行相应的处理。 注意:以上代码只是一个简单示例,实际应用中还需要考虑异常处理、锁的超时时间、可重入性等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值