本文介绍策略模式对if-else业务分派逻辑的优化
文章目录
应用场景
最近写了一个服务:根据优惠券的类型resourceType和编码resourceId来 查询 发放方式grantType
实现方式:
- 根据优惠券类型resourceType -> 确定查询哪个数据表
- 根据编码resourceId -> 查询派发方式grantType
优惠券有多种类型,分别对应了不同的数据库表:
- 红包
- 购物券
- QQ会员
- 外卖会员
实际的优惠券远不止这些,这个需求是要我们写一个业务分派的逻辑
第一思路一般是if-else 、swtich case:
switch(resourceType){
case "红包":
查询红包的派发方式
break;
case "购物券":
查询购物券的派发方式
break;
case "QQ会员" :
...
break;
case "外卖会员" :
...
break;
......
default : logger.info("查找不到该优惠券类型resourceType以及对应的派发方式");
break;
}
这么写if-else有个坏处:
- 就是如果判断的情况很多且单个if 语句块的代码很多行 的话,那 整个if-else的代码块就太长了,可读性下降。
- 并且由于 整个 if-else的代码有很多行,也不方便修改,可维护性低。
那么我们就尝试对 if-else 的业务分派 逻辑优化一下
策略模式
定义就不念了,说人话,策略模式的结构就是:
- 一个支持所有算法的公共抽象类 /接口:即任意一个 if 判断完后,都会执行该接口的方法
- 具体策略的实现类:查询红包派发方式的逻辑写在一个类里面,购物券写在另一个类
- 客户端调用的入口:通过持有 公共接口的引用,在创建对象的时候利用多态来执行具体的策略算法。
上代码:
一、公共接口
public abstract class Strategy{
//定义支持所有算法的公共接口
public abstract String query();
}
客户端执行具体的策略的时候,就Strategy strategy = new ConcreteStrategy01()
二、具体的策略实现类
继承公共接口,给里面的抽象方法加内容:
查询红包的发放方式:
//查询红包redPaper 发放方式
class ConcreteStrategy01 extends Strategy{
public String query(){
return "每周末9点发放";
}
}
查询购物券的发放方式:
//查询购物券shopping的发放方式
class ConcreteStrategy02 extends Strategy{
public String query(){
return "每周三20点发放";
}
}
三、客户端调用的入口
要持有 公共接口的引用,不然没法通过多态 new ConcreteStrategy01() 或者 new ConcreteStrategy02()
来获得具体的策略实现 [红包的查询方式、购物券的查询方式]
class Context{
//持有公共接口的引用,后续通过多态来获取[红包、购物券]的实现类
Strategy strategy;
public Context(Strategy strategy){
this.strategy=strategy;
}
public String ContextInterface(){
return strategy.query();
}
}
客户端执行具体策略:
值得注意的是:策略模式在具体的业务分派的时候,依然采用if-else的方式,只是说它比单纯的if-else好在可维护性比较好,如果要更改某一个业务逻辑,只需要去修改对应的类即可。
比如:查询红包的派发方式grantType:
回顾一下产品需求:根据优惠券类型resourceType和编码resourceId来查询派发方式grantType
具体操作是由优惠券类型resourceType判断去哪个表查,然后根据编码resourceId查出对应的派发方式grantType
class Test{
//客户端执行具体策略的测试方法
public static void main(String[] args){
String resourceType="红包";
String grantType;
switch(resourceType){
case "红包":
Context context01=new Context(new ConcreteStrategy01());
grantType=context01.ContextInterface();
break;
case "购物券":
Context context02=new Context(new ConcreteStrategy02());
grantType=context02.ContextInterface();
break;
default:
throw new IllegalStateException("Unexpected value: " + resourceType);
}
}
}
我把策略的具体实现给简化了
执行的结果:
策略模式的优点和缺点
优点
- 可维护性好,如果要修改红包的派发逻辑,只需要去修改对应的类ConcreteStrategy01 即可。
缺点
- 没法俯视整个业务分派逻辑
- 策略类增多