从排序说起
如上:一个最简单的排序功能,实现了对一个int数组排序。
但现在如果是要对一个String、一个Cat类、或者一个Dog类进行排序呢?
假如要实现对猫排序,改造代码:
-
新增一个Cat类,有weight和height两个属性
-
新增一个CatSorter,对cat的weight进行排序
问题: -
假如要改成对Dog的weight排序呢?也许可以通过修改Sorter,传入一个泛型来支持对Dog的weight排序
-
假如要改成对height进行排序呢?,那就得新增一个HeightSorter支持Height的比较,再修改Main方法的newSorter
-
假如要对Dog的Height排序?或者又要对String排序?或者又要对Dog、Cat以后可能新增的任意属性进行排序?就算用了泛型,还是得建很多个Sorter支持对不同的属性排序,且每次都要修改main方法new出不同的sorter
再次改造
抽象出一个Comparator接口,表示比较策略的抽象,为了支持Cat\Dog\以及未来可能新增的类的比较,传入一个泛型
public interface Comparator<T> {
int compare(T o1, T o2);
}
在sort方法中,入参传入一个比较策略的实例,调用比较策略的compare方法,进行对象的比较
public class Sorter<T> {
public void sort(T[] arr, Comparator<T> comparator) {
for(int i=0; i<arr.length - 1; i++) {
int minPos = i;
for(int j=i+1; j<arr.length; j++) {
minPos = comparator.compare(arr[j],arr[minPos])==-1 ? j : minPos;
}
swap(arr, i, minPos);
}
}
//sort(int)
void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
测试
- 如果要对猫的身高进行排序,新建一个猫的身高比较策略就行
- 如果要对狗排序,新建狗的策略 …
- 这就是对修改关闭-对新增放开的原则——开闭原则
总结:
- List item
延申
在实际项目中的应用
有短信发送的需求,最开始是用的A提供方的短信接口,后面又改成了B,以后还可能改成C
思路:
- 短信发送策略接口
- A,B,C三种不同的策略实现
- 在业务代码的sendSMS(param,strategy)方法的入参中传入一个策略实例,方法体中调用策略实例的具体发送方法
- 可以在配置文件中定义一个参数作为具体策略(具体策略实现的类名),在业务代码中获取此参数后通过反射获取其对象,然后以此对象作为策略参数传入sendSMS(param,strategy)
- 如果是spring项目,在strategy实例中注入了其它的bean,那么是不能用反射来生成的(不是spring初始化的,其注入的bean将是null)。可以考虑给strategy指定beanName,交给spring来管理,获取时通过配置文件取不同的beanName,再从context中来获取对应的strategy实例