设计模式之策略+工厂
前言
随着业务发展,需求只会越来越复杂,为了考虑到各种各样的情况,代码中不可避免的会出现很多 if-else。 一旦代码中if-else过多,就会大大的影响其可读性和可维护性。 可读性很差,过多的if-else嵌套,会使阅读代码的人很难理解到底是什么意思。尤其是那些没有注释的代码。其次是可维护性,因为if-else特别多,想要新加一个分支的时候,就会很难添加,极其容易影响到其他的分支。 其实,if-else是有办法可以消除掉的,其中比较典型的并且使用广泛的就是借助策略模式和工厂模式,准确的说是利用这两个设计模式的思想,彻底消灭代码中的if-else。提示:以下是本篇文章正文内容(基于SpringBoot 环境),下面案例可供参考
一、业务需求
假设我们要做一个多支付方式扣款的功能 需求如下:
1、设置多个支付方式,包含微信,支付宝,银联
2、其中微信优惠0.5元.支付宝优惠0.7元,银联优惠1元.
3、如果使用微信支付订单满30元优惠0.5元 满50元优惠1元
3、支付宝支付订单满40优惠 0.7元,满80元优惠2元
伪代码:
//价格单位(分)
public boolean pay(int plat,Long money){
long price=money;
if(plat==微信支付){
price-=50;
if(订单金额>=50元){
price-=100;
}else if(订单金额>=30元){
price-=50;
}
}
if(plat==支付宝支付){
price-=70;
if(订单金额大于>=80元){
price-=200;
}else if(订单金额>=40){
price-=70;
}
}
if(plat==银联支付){
price-=100;
}
return price;
}
以上,就是对于这个需求的一段价格计算逻辑,使用伪代码都这么复杂,如果是真的写业务代码,那复杂度可想而知。
这样的代码中,有很多if-else,并且还有很多的if-else的嵌套,无论是可读性还是可维护性都非常低。
如果后续更改其中一个支付方式那么在原方法上更改很有可能会导致其他支付方式出现异常。
那么,如何改善呢?
二.实现
策略模式
1.先来定义一个接口:
/**
* @author aki
* 支付策略接口
*/
public interface PayStrategy {
/**
* 优惠后支付金额
*/
long discountPayMoney(Long money, Integer plat);
}
2.接着定义几个策略类:
/**
* 微信支付
*/
@Slf4j
@Component("weChatPay")
public class WeChatPayStrategy implements PayStrategy {
/**
* @author aki
* 优惠后支付金额
* @param money
* @param plat
*/
@Override
public long discountPayMoney(Long money, Integer plat) {
long price=money;
price-=50;
if(订单金额>=50元){
price-=100;
}else if(订单金额>=30元){
price-=50;
}
return price;
}
}
/**
* @author aki
* 银联支付
*/
@Slf4j
@Component("unionpayPay")
public class UnionpayPayStrategy implements PayStrategy {
/**
* 优惠后支付金额
*
* @param money
* @param plat
*/
@Override
public long discountPayMoney(Long money, Integer plat) {
long price=money;
price-=100;
return price;
}
}
/**
* @author aki
* 支付宝支付
*/
@Slf4j
@Component("alipayPay")
public class AlipayPayStrategy implements PayStrategy {
/**
* @author aki
* 优惠后支付金额
*
* @param money
* @param plat
*/
@Override
public long discountPayMoney(Long money, Integer plat) {
long plat=money;
price-=70;
if(订单金额大于>=80元){
price-=200;
}else if(订单金额>=40){
price-=70;
}
return price;
}
}
以上,就是一个例子,可以在代码中new出不同的会员的策略类,然后执行对应的计算价格的方法。这个例子以及策略模式的相关知识。接下来就不在写策略怎么使用啦. 直接搭配工厂模式来操作.
工厂模式
工厂类PayFactory负责创建策略的工厂。使用ConcurrentHashMap是防止多线程操作的时候出现问题。同时还要注意@Service注解。
/**
*
*工厂类
*/
@Service
@Slf4j
public class PayFactory {
@Autowired
Map<String, PayStrategy > map = new ConcurrentHashMap<>();
public PayStrategy getStrategy(String componentName) {
PayStrategy strategy= map.get(componentName);
if (strategy == null) {
log.error("没有获取工厂类 componentName={}", componentName);
//此处可以写个自定义异常抛出去.也可以return null 全看自己操作了.
}
return strategy;
}
}
运行结果:
@RestController
public class TestController {
@Autowired
PayFactory payFactory;
@RequestMapping(value = "test")
public Long test(Integer plat) {
// plat==0 微信 ,1银联,2支付宝
// 因为策略类组件名不能重复所以我们最好是做一个常量池来进行类型转换.这里就不一 一去写了.
PayStrategy alipayPay = payFactory.getStrategy("alipayPay");
Long price = alipayPay.discountPayMoney(10000L);
return price;
}
}
策略类里 必须要加@Component 并声明组件名(组件名不能重复.)springq启动的时候,spring的工厂类就会创建对象。用map封装,在这里key就是@Component的value值,value就是这个类
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了代理+工厂的使用,从而减少了大部分if判断 可读性大大提升.代理+工厂还有其他方法实现就不一一介绍了. 感谢大家阅读.