设计模式必知必会:策略模式

it2026-03-07  3

本文介绍策略模式对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 即可。

缺点

没法俯视整个业务分派逻辑策略类增多
最新回复(0)