利用策略模式避免过多if
背景
对于业务开发来说,业务逻辑的复杂是必然的,随着业务发展,需求只会越来越复杂,为了考虑到各种各样的情况,代码中不可避免的会出现很多if-else。一旦代码中if-else过多,就会大大的影响其可读性和可维护性。
假设需求
| 12
 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的方法
定义用户支付接口
| 12
 3
 4
 5
 6
 7
 
 | public interface UserPayService {
 
 
 
 public BigDecimal quote(BigDecimal orderPrice);
 }
 
 | 
为了方便从Spring中获取UserPayService的各个策略类(也就是实现的接口),创建一个工厂类:
| 12
 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的属性初始化后都会执行该方法。
| 12
 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
 
 | @Servicepublic 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);
 }
 }
 
 | 
优化后计算价格的代码
| 12
 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