利用策略模式避免过多if
背景
对于业务开发来说,业务逻辑的复杂是必然的,随着业务发展,需求只会越来越复杂,为了考虑到各种各样的情况,代码中不可避免的会出现很多if-else。一旦代码中if-else过多,就会大大的影响其可读性和可维护性。
假设需求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public BigDecimal calPrice(BigDecimal orderPrice, String buyerType) {
if (用户是专属会员) { if (订单金额大于30元) { returen 7折价格; } }
if (用户是超级会员) { return 8折价格; }
if (用户是普通会员) { if(该用户超级会员刚过期并且尚未使用过临时折扣){ 临时折扣使用次数更新(); returen 8折价格; } return 9折价格; } return 原价; }
|
替换if的方法
定义用户支付接口
1 2 3 4 5 6 7
| public interface UserPayService {
public BigDecimal quote(BigDecimal orderPrice); }
|
为了方便从Spring中获取UserPayService的各个策略类(也就是实现的接口),创建一个工厂类:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class UserPayServiceStrategyFactory {
private static Map<String,UserPayService> services = new ConcurrentHashMap<String,UserPayService>();
public static UserPayService getByUserType(String type){ return services.get(type); }
public static void register(String userType,UserPayService userPayService){ Assert.notNull(userType,"userType can't be null"); services.put(userType,userPayService); } }
|
借用Spring种提供的InitializingBean接口将各个实现策略类注册进入工厂类中,这个接口为Bean提供了属性初始化后的处理方法,它只包括afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| @Service public class ParticularlyVipPayService implements UserPayService,InitializingBean {
@Override public BigDecimal quote(BigDecimal orderPrice) { if (消费金额大于30元) { return 7折价格; } }
@Override public void afterPropertiesSet() throws Exception { UserPayServiceStrategyFactory.register("ParticularlyVip",this); } }
@Service public class SuperVipPayService implements UserPayService ,InitializingBean{
@Override public BigDecimal quote(BigDecimal orderPrice) { return 8折价格; }
@Override public void afterPropertiesSet() throws Exception { UserPayServiceStrategyFactory.register("SuperVip",this); } }
@Service public class VipPayService implements UserPayService,InitializingBean {
@Override public BigDecimal quote(BigDecimal orderPrice) { if(该用户超级会员刚过期并且尚未使用过临时折扣){ 临时折扣使用次数更新(); returen 8折价格; } return 9折价格; }
@Override public void afterPropertiesSet() throws Exception { UserPayServiceStrategyFactory.register("Vip",this); } }
|
优化后计算价格的代码
1 2 3 4 5 6
| public BigDecimal calPrice(BigDecimal orderPrice,User user) {
String vipType = user.getVipType(); UserPayService strategy = UserPayServiceStrategyFactory.getByUserType(vipType); return strategy.quote(orderPrice); }
|
AOP+自定义注解+策略模式 记录操作日志,避免过多的if
https://github.com/haoxiaoyong1014/springboot-examples/tree/master/strategy-aop
参考
https://juejin.im/post/5dad23685188251d2c4ea2b6#comment