每次说起设计模式脑子里总是想起大学里学的23中设计模式。23中设计模式,能记住的屈指可数,在工作中用到的更是少之又少。当然,设计模式听着总是感觉很高大上,自己那点业务需求有点简单的if-else,三下五除二就打完收工了,如果绞尽脑汁弄了设计模式,代码量倍增,看不到到底好在哪里,反而增加了工作量。这次就用一个需求说一下,策略模式的使用。
首先,还是老生常谈,了解一下策略模式的定义。
在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。
一个类的行为或其算法可以在运行时更改,说白了就是if-else。那么为什么不用if-else吶?
假如有这么一个需求:
一批客户订单,一批商家。每个商家有个分值,可以理解为权重。需要将这些待处理的订单按设置的分派规则分派给这些商家
分派规则A: 按照商家分值从高到低依次循环分派,直到分派完毕
分派规则B: 按照商家分值在总分值中的比例,从订单中按照比例分派
大致实现流程
//1.获取待分派订单
//2.获取商家
//3.根据分派规则分派
if(规则a){
执行规则a分派逻辑
} else if(规则b){
执行规则b分派逻辑
}
//4.结束
半个小时你就写完了需求。半个月后产品又加了两个分派规则:
分派规则C: 按照不同分值分组,按照不同分值比例分派订单,同组内轮询分派
分派规则D: 按照不同分值分组,按照不同分值比例分派订单,同组内按照商家客户评级排序依次分派
于是接着加if-else
//3.根据分派规则分派
if(规则a){
执行规则a分派逻辑
} else if(规则b){
执行规则b分派逻辑
}else if(规则c){
执行规则a分派逻辑
} else if(规则d){
执行规则b分派逻辑
}
这个时候有没有这块代码有点难受呀,这时候产品接着加分派规则,然后有的分派规则交给其他同事开发,大家接着填if-else,代码开始冲突,各种分派逻辑中又嵌套各种if-else。最后这块分派订单的逻辑就变成了谁也不想维护的又臭又长的if-else的嵌套代码毒瘤。后面可能更改一个if,牵一发而全崩盘。
这个情况其实可以考虑使用策略模式。我们用策略模式简单改造一下。
//分派接口
interface BaseDispatchService{
void doDispatch(订单,商家);
}
规则A分派实现类
@Service("aDispatch")
class ADispatchService implements BaseDispatchService{
void doDispatch(订单,商家){//TODO};
}
规则B分派实现类
@Service("bDispatch")
class BDispatchService implements BaseDispatchService{
void doDispatch(订单,商家){//TODO};
}
执行分派流程:
class Dispatch{
//读取设置的分配规则,假设是在阿波罗配置文件中,也可是枚举、数据库中的设置等
@Value("${dispatchCode}")
private String dispatchCode;
@Autowired
private Map<String, BaseDispatchService> dispatchServiceMap;
void dispatch(){
//1.获取待分派订单
//2.获取商家
//3.根据分派规则分派
dispatchServiceMap.get(dispatchCode).doDispatch(xx,xx);
//4.结束
}
}
如果有了新的分派规则,只需求实现对应的分配规则即可,对原来的分派逻辑没有任何影响。
该策略方式借助于spring的ioc方式,将同一类型的bean注入到一个Map中。
也有使用上下文实现的、策略工厂,大体也是将不同策略对应关系存储到一个容器中。
感兴趣的可以自行百度。这里不再赘述。
到这里,我们的代码看着不那么low了,对同事也很友好,维护成本也低了,nice。
总结:
优点:
1、算法可以自由切换。
2、避免使用多重条件判断。
3、扩展性良好。
缺点:
1、策略类会增多。
2、所有策略类都需要对外暴露。
使用场景:
1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
2、一个系统需要动态地在几种算法中选择一种。注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。
工作中也用了几次策略模式,效果还可以。
其实到现在,用的最多的也不外乎策略模式、单例模式、工厂模式等,因为大部分的业务场景其实就是if-else的组合。
23中设计模式用的就那么少吗?一点也不是,设计模式说白了就是前人总结的优秀的开发经验,经验就是踩过坑总结出来的教训。
我们使用的各种优秀的开源框架里,处处有着设计模式的身影。只是我们在享受优秀框架带给我们便利的同时,忘了框架底层中设计模式的优点罢了。
准备看看设计模式在优秀开源框架中的应用,它山之石可以攻玉。Nice!