过多的if-else代码和嵌套,会使阅读代码的人很难理解到底是什么意思。尤其是那些没有注释的代码。其次是可维护性,因为if-else特别多,if-else是有办法可以消除掉的,其中比较典型的并且使用广泛的就是借助策略模式和工厂模式,准确的说是利用这两个设计模式的思想,彻底消灭代码中的if-else。

传统用if else (伪代码)

public BigDecimal calPrice(BigDecimal orderPrice, String buyerType) {
if (用户是专属会员) {
 if (订单金额大于30元) {
 returen 7折价格;
 }
 }if (用户是超级会员) {
 return 8折价格;
 }if (用户是普通会员) {
 if(该用户超级会员刚过期并且尚未使用过临时折扣){
 临时折扣使用次数更新();
 returen 8折价格;
 }
 return 9折价格;
 }
 return 原价;
 }策略模式
首先,定义一个接口:
/**
• @author mhcoding
 */
 public interface UserPayService {
/**
• 计算应付价格
 */
 public BigDecimal quote(BigDecimal orderPrice);
 }接着定义几个策略类:
/**
• @author mhcoding
 */
 public class ParticularlyVipPayService implements UserPayService {
@Override
 public BigDecimal quote(BigDecimal orderPrice) {
 if (消费金额大于30元) {
 return 7折价格;
 }
 }
 }public class SuperVipPayService implements UserPayService {
@Override
 public BigDecimal quote(BigDecimal orderPrice) {
 return 8折价格;
 }
 }public class VipPayService implements UserPayService {
@Override
 public BigDecimal quote(BigDecimal orderPrice) {
 if(该用户超级会员刚过期并且尚未使用过临时折扣){
 临时折扣使用次数更新();
 returen 8折价格;
 }
 return 9折价格;
 }
 }利用工厂模式让代码自己判断使用策略
/**
• @author mhcoding
 */
 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);
 }
 }这个UserPayServiceStrategyFactory中定义了一个Map,用来保存所有的策略类的实例,并提供一个getByUserType方法,可以根据类型直接获取对应的类的实例。
有了这个工厂类之后,计算价格的代码即可得到大大的优化:
/**
• @author mhcoding
 */
 public BigDecimal calPrice(BigDecimal orderPrice,User user) {
String vipType = user.getVipType();
 UserPayService strategy = UserPayServiceStrategyFactory.getByUserType(vipType);
 return strategy.quote(orderPrice);
 }最后我们利用spring调用register方法,把Spring通过IOC创建出来的Bean注册进去就行了。
这种需求,可以借用Spring种提供的InitializingBean接口,这个接口为Bean提供了属性初始化后的处理方法,它只包括afterPropertiesSet方法,凡是继承该接口的类,在bean的属性初始化后都会执行该方法。
将前面的各个策略类稍作改造:
/**
• @author mhcoding
 */
 @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);
 }
 }

只需要每一个策略服务的实现类都实现InitializingBean接口,并实现其afterPropertiesSet方法,在这个方法中调用UserPayServiceStrategyFactory.register即可。

这样,在Spring初始化的时候,当创建VipPayService、SuperVipPayService和ParticularlyVipPayService的时候,会在Bean的属性初始化之后,把这个Bean注册到UserPayServiceStrategyFactory中。