干掉if else 优化业务代码!

干掉if else 优化业务代码!


前言

随着业务发展,需求只会越来越复杂,为了考虑到各种各样的情况,代码中不可避免的会出现很多if-else。怎么去优化我们的代码,在代码中怎么避免出现很多if-else呢。请继续往下看哈。


一、解决if else的办法

if-else是有办法可以消除掉的, 其中比较典型的并且使用广泛的就是借助策略模式和工厂模式,准确的说是利用这两个设计模式的思想, 彻底消灭代码中的if-else。
如果不清楚的朋友请继续往下看, 下面就简单的科普一下工厂模式和设计模式的优缺点,再结合实际的项目案例来给大家分析。

二、策略模式

介绍

  • 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
  • 主要解决:在有多种算法相似的情况下,使用 if…else
    所带来的复杂和难以维护。

优缺点

  1. 算法可以自由切换。
  2. 避免使用多重条件判断。
  3. 扩展性良好。
  4. 策略类会增多。
  5. 所有策略类都需要对外暴露。

使用定义

在旅行出游时搭乘工具有很多, 有人选择骑自行车、坐汽车,坐地铁,每一种搭乘工具都是一个策略


三、工厂模式

介绍

  • 意图:定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
  • 主要解决:主要解决接口选择的问题。

优缺点

  1. 一个调用者想创建一个对象,只要知道其名称就可以了
  2. 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以
  3. 调用者只关心产品的接口。
  4. 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

使用定义

您需要一辆汽车有宝马,本田,福特,特斯拉 等等 ,只要工厂里面有的都可可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。

案例说明

假设我们店铺开张,有这样的以下需求:

1、店铺为了促销,设置了多种会员优惠,其中包含 普通卡会员消费满30元打9折、金卡会员打8折和白金卡会员消费满150元打6折如果没有满足也可以打7折设置这三种优惠折扣。
2、希望用户在付款的时候,根据用户的会员等级,就可以知道用户符合哪种折扣策略,进而进行打折,计算出应付金额。

那么,我们可以看到以下代码:

public double calPrice(double orderPrice, String vipType) throws Exception {
	// 普通卡会员
	if (vipType.equals("cardMember") ) {
		// 订单金额大于30元
		 if (orderPrice > 30) {
			 // 9折价格
            return MathUtil.mul(orderPrice, 0.9);
        // 返回原价
        } else {
			return orderPrice;
		}
	}
	// 金卡会员
	if (vipType.equals("goldCardMember")) {
	  // 8折价格
	  return MathUtil.mul(orderPrice, 0.8);
	}
	// 白金卡会员
	if (vipType.equals("platinumCardMember")) {
		// 订单金额大于150元
		 if (orderPrice > 150) {
			 // 6折价格
            return MathUtil.mul(orderPrice, 0.6);
        // 7折优惠
        } else {
        	  return MathUtil.mul(orderPrice, 0.7);
        }
	}
	throw new  Exception("无法识别该会议类型: ".concat(vipType));
}

这样的代码中,有很多if-else,并且还有很多的if-else的嵌套,无论是可读性还是可维护性都非常低。

那么,如何改善呢?

引入策略模式

接下来,我们尝试引入策略模式来提升代码的可维护性和可读性。

首先,定义一个接口:

/**
 * 支付服务
 * 
 * @author Administrator
 *
 */
public interface IPayService {

	 /**
     * 计算应付价格
     */
    public Double calculate(double orderPrice);
}

接着定义几个策略类

@Service
public class CardMemberService implements IPayService {

	@Override
	public Double calculate(double orderPrice) {
		// 订单金额大于30元
		 if (orderPrice > 30) {
			 // 9折价格
           return MathUtil.mul(orderPrice, 0.9);
       // 返回原价
       } else {
       	return orderPrice;
       }
	}
}
@Service
public class GoldCardMemberService  implements IPayService{

	@Override
	public Double calculate(double orderPrice) {
		  // 8折价格
		  return MathUtil.mul(orderPrice, 0.8);
	}
}
@Service
public class PlatinumCardMember  implements IPayService {

	@Override
	public Double calculate(double orderPrice) {
		// 订单金额大于150元
		 if (orderPrice > 150) {
			 // 6折价格
           return MathUtil.mul(orderPrice, 0.6);
       // 7折优惠
       } else {
       	  return MathUtil.mul(orderPrice, 0.7);
       }
	}
}

引入了策略之后,我们可以按照如下方式进行价格计算:

public double calPrice(double orderPrice, String vipType) throws Exception {
	// 普通卡会员
	if (vipType.equals("cardMember") ) {
		IPayService cardMemberService = SpringUtil.getBean(CardMemberService.class);
		return cardMemberService.calculate(orderPrice);
	}
	// 金卡会员
	if (vipType.equals("goldCardMember")) {
		IPayService goldCardMemberService = SpringUtil.getBean(GoldCardMemberService.class);
		return goldCardMemberService.calculate(orderPrice);
	}
	// 白金卡会员
	if (vipType.equals("platinumCardMember")) {
		IPayService platinumCardService = SpringUtil.getBean(PlatinumCardMember.class);
		return platinumCardService.calculate(orderPrice);
	}
	throw new  Exception("无法识别该会议类型: ".concat(vipType));
}

注意这里写的代码是web项目中代码,以上就是一个例子,通过不同的会员的策略类,然后执行对应的计算价格的方法。

通过以上代码,我们发现,代码可维护性和可读性好像是好了一些,但是好像并没有减少if-else啊。也就是说,虽然在计算价格的时候没有if-else了,但是选择具体的策略的时候还是不可避免的还是要有一些if-else。

我们换种思维想一下, 看看还有哪些设计模式可以帮我们解决这类问题呢,我们知道工厂模式的主要特点就是解决接口的选择问题这不正正是我们需要的吗。话不多说继续开干,不是很了解工厂模式的朋友可以看一下工厂模式的章节。

引入工厂模式

接下来我们看如何借助Spring和工厂模式,解决上面这些问题。

为了方便我们从Spring中获取的各个策略类,我们创建一个PayServiceFactory工厂类:

/**
 * 支付策略工厂
 * 
 * @author Administrator
 *
 */
public class PayServiceFactory {

	private static Map<String, IPayService> servicesMap = new ConcurrentHashMap<String, IPayService>();

	public static IPayService getPayService(String type) {
		return servicesMap.get(type);
	}
	
    public static void register(String type, IPayService payService){
        Assert.notNull(type, "注册类型不能为null ");
        servicesMap.put(type, payService);
    }
}

这个PayServiceFactory 中定义了一个Map,用来保存所有的策略类的实例,并提供一个getPayService方法,可以根据类型直接获取对应的类的实例。

有了这个工厂类之后,计算价格的代码即可得到大大的优化

还记得我们定义的PayServiceFactory 中提供了的register方法吗?他就是用来注册策略服务的。

接下来,我们就想办法调用register方法,怎么在启动项目的时候就自动注册上去呢,这时候我们想到借助class的构造器特征在加载class的时候就注册上去。如下代码

@Service
public class CardMemberService implements IPayService {
	
	public CardMemberService() {
		PayServiceFactory.register("cardMember", this);
	}

	@Override
	public Double calculate(double orderPrice) {
		// 订单金额大于30元
		 if (orderPrice > 30) {
			 // 9折价格
           return MathUtil.mul(orderPrice, 0.9);
       // 返回原价
       } else {
       	return orderPrice;
       }
	}
}
@Service
public class GoldCardMemberService  implements IPayService {
	
	public GoldCardMemberService() {
		PayServiceFactory.register("goldCardMember", this);
	}

	@Override
	public Double calculate(double orderPrice) {
		  // 8折价格
		  return MathUtil.mul(orderPrice, 0.8);
	}
}
@Service
public class PlatinumCardMember  implements IPayService {
	
	public PlatinumCardMember() {
		PayServiceFactory.register("platinumCardMember", this);
	}

	@Override
	public Double calculate(double orderPrice) {
		// 订单金额大于150元
		 if (orderPrice > 150) {
			 // 6折价格
           return MathUtil.mul(orderPrice, 0.6);
       // 7折优惠
       } else {
       	  return MathUtil.mul(orderPrice, 0.7);
       }
	}
}

有了这个工厂类之后,计算价格的代码即可得到大大的优化:

public double calPrice(double orderPrice, String vipType) throws Exception {
	IPayService payService = PayServiceFactory.getPayService(vipType);
	return payService.calculate(orderPrice);
}

总结

本文,我们通过策略模式、工厂模式,彻底消灭了一坨if-else。

对于设计模式的学习,重要的是学习其思想,而不是代码实现。

希望通过这样的文章,希望能让更多人在日常开发中减少if else代码, 提升了代码的可读性以及可维护性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值