前言
零基础快速上手《设计模式》点击如下传送门
秒懂—设计模式https://blog.csdn.net/weixin_56232016/article/details/136766136
“设计模式学的是思想,而不是套用模板”
概念看不懂时可以参考个人理解
策略模式
定义
策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户端。
目标
策略模式通过对算法进行封装,将算法的使用和算法的实现进行分隔开,并委派给不同的对象对这些算法进行管理。用于取代多重if-else硬编码情况。
个人理解:对于在业务逻辑实现上,不再使用if-else进行条件判断要执行哪个逻辑,而是把每个算法进行封装成一个策略类,通过在环境类中设置不同的具体策略类执行不同的算法实现。
角色:
抽象策略类(Strategy):定义了策略对象的公共接口或抽象类,规定了具体策略类必须实现的方法。
具体策略类(Concrete Strategy):负责将客户端请求委派给具体的策略对象执行。
环境类(Context):负责将客户端请求委派给具体的策略对象执行。
UML
代码实现
环境类:
public class Context {
public void invoke(Strategy strategy){
// 业务操作
strategy.algorithmInterface();
}
}
抽象算法类:
public interface Strategy {
void algorithmInterface();
}
具体算法类:
public class ConcreteStrategy implements Strategy{
@Override
public void algorithmInterface() {
// 具体算法
}
}
使用场景
- 算法需要自由切换的场景
- 多个策略类具有相同的行为但具体实现方式不同
- 需要屏蔽算法规则的场景
优缺点:
优:
- 扩展性良好,策略模式是对“开闭原则”的完美支持,可以在不修改原代码的情况下,灵活增加新的算法。
- 避免使用多重条件语句
- 实现算法自由切换。提供相同行为的不同实现,客户端可以根据条件选择具体的实现.
缺:
- 策略模式会创造很多策略类,难以维护
- 所有策略需要对外暴露
个人理解
当我们在项目中需要根据条件执行不同的操作时,硬编码就直接通过if-else的方式解决。这样带来的后果就是每次有新的执行逻辑需要添加时,就需要修改这段if-else的代码块,这样就与“开闭原则”相违背了,而且也不利于代码的维护。
不知道“开闭原则”是什么?👉👉👉传送门
那么怎么解决这个问题呢?利用java的多态性,在执行相同行为的时候,我们并不直接使用具体策略,而是通过抽象策略的引用执行相同的行为(接口函数),在运行时根据引用对应的具体策略完成行为。
举个栗子就清楚了,在jdk中,对数组的排序(Arrays.sort)运用了策略模式的思想。
当我们在使用Arrays.sort进行数组排序时,会通过Comparator参数传入具体的比较算法。
Integer[] nums = {1,2,3,4,6,6,9};
Arrays.sort(nums, Comparator.comparingInt(a -> Math.abs(a - 5)));
System.out.println(Arrays.toString(nums));
在这里,Arrays.sort()即是环境,Comparator是抽象策略, Comparator的实现类是具体策略类。
下面是Arrays.sort()的有部分源码
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (c == null) {
sort(a);
} else {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, 0, a.length, c, null, 0, 0);
}
}
是不是与上面的Strategy类相似。
那么,在实际开发中,当我们遇到某一行为的执行后续需要添加新的算法实现时,即可通过这种行为模式,确保后续增加新的算法不用改变原有的代码