Java 设计模式之策略模式,spring boot具体实现案例

代码基于SpringBoot
需求假设:

平台有不同的会员等级,不同的会员等级消费折扣不一样
1.普通用户没折扣
2.vip1拥有9折优惠(可以复杂化加优惠券,这里举例就简单化了)
3.vip2拥有8折优惠(可以复杂化加优惠券,这里举例就简单化了)
4.vip3拥有7折优惠(可以复杂化加优惠券,这里举例就简单化了)

当然,用if-else语句是可以实现如上需求的,但是无论是可读性或者是可维护性都不高,可以用策略模式去改善,代码如下:

1.定义用户等级类型

// 共有四种用户类型的枚举,对应不同的折扣优惠方式
@Getter
public enum UserType {
    USER,
    VIP1,
    VIP2,
    VIP3
}

2.定义统一计算折扣接口,让不同的用户类型去具体实现

public interface UserPayService {

    /**
     * 用户类型解析
     *
     * @return 用户类型
     */
    UserType geinUserType();

    /**
     * 计算订单价格
     *
     * @param orderPrice 原价
     * @return 折后价
     */
    BigDecimal calcPrice(BigDecimal orderPrice);
}

3.不同的用户实现统一计算接口

// 普通用户的计算价格方式实现
// 这个注解是要的,让spring实例化
@Component
public class UserPayServiceImpl implements UserPayService {
    @Override
    public UserType geinUserType() {
        return UserType.USER;
    }

    @Override
    public BigDecimal calcPrice(BigDecimal orderPrice) {
        // 普通用户 没折扣
        return orderPrice;
    }
}
// Vip1用户的计算价格方式实现
// 这个注解是要的,让spring实例化
@Component
public class Vip1PayServiceImpl implements UserPayService {
    @Override
    public UserType geinUserType() {
        return UserType.VIP1;
    }

    @Override
    public BigDecimal calcPrice(BigDecimal orderPrice) {
        // vip1 9折(或者叠加优惠券)
        BigDecimal discount = new BigDecimal("0.9");
        return orderPrice.multiply(discount);
    }
}
// Vip2用户的计算价格方式实现
// 这个注解是要的,让spring实例化
@Component
public class Vip2PayServiceImpl implements UserPayService {
    @Override
    public UserType geinUserType() {
        return UserType.VIP2;
    }

    @Override
    public BigDecimal calcPrice(BigDecimal orderPrice) {
        // vip1 8折 (或者叠加优惠券)
        BigDecimal discount = new BigDecimal("0.8");
        return orderPrice.multiply(discount);
    }
}
// Vip3用户的计算价格方式实现
// 这个注解是要的,让spring实例化
@Component
public class Vip3PayServiceImpl implements UserPayService {
    @Override
    public UserType geinUserType() {
        return UserType.VIP3;
    }

    @Override
    public BigDecimal calcPrice(BigDecimal orderPrice) {
        // vip1 7折(或者叠加优惠券)
        BigDecimal discount = new BigDecimal("0.7");
        return orderPrice.multiply(discount);
    }
}

4.实现spring的ApplicationContextAware接口进行bean自定义管理的策略类

// 这个注解是要的,让spring实例化
@Component
public class PayStrategyService implements ApplicationContextAware {

    private Map<UserType, UserPayService> userPayServiceMap = new ConcurrentHashMap<>();

    public BigDecimal calcPrice(UserType userEnum, BigDecimal orderPrice) {
        UserPayService userPayService = this.userPayServiceMap.get(userEnum);
        if (userPayService != null) {
            return userPayService.calcPrice(orderPrice);
        }
        return orderPrice;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, UserPayService> userPayServiceBeans = applicationContext.getBeansOfType(UserPayService.class);
        // 把不同的用户类型UserType和其实现类一一对应放入Map
        userPayServiceBeans.values().forEach(userPayService -> userPayServiceMap.put(userPayService.geinUserType(), userPayService));
    }
}

5.使用方式,此处使用springboot test测试

@SpringBootTest
public class TestApplication {

	// 策略类注入
    @Autowired
    private PayStrategyService payStrategyService;

    @Test
    public void Test() {
        BigDecimal orderPrice = new BigDecimal(1000);
        System.out.println("普通用户最终价格:" + payStrategyService.calcPrice(UserType.USER, orderPrice));
        System.out.println("Vip1用户最终价格:" + payStrategyService.calcPrice(UserType.VIP1, orderPrice));
        System.out.println("Vip2用户最终价格:" + payStrategyService.calcPrice(UserType.VIP2, orderPrice));
        System.out.println("Vip3用户最终价格:" + payStrategyService.calcPrice(UserType.VIP3, orderPrice));

    }
}

结果如下:

Java 设计模式之策略模式,spring boot具体实现案例

上一篇:根据需求,完成如下代码(按照标准格式写),并在测试类中进行测试?


下一篇:double转String结果为指数问题