策略模式
场景:
当我们有猫这个对象时,需要根据猫的属性进行排序(比如根据体重排序)
- 猫有两个属性 身高 提供
- implements Comparable 实现一个比较方法
- 代码实现根据体重进行排序 comparateTo(Cat a)
public class Cat implements Comparable<Cat> {
private Integer weight;
private Integer height;
@Override
public String toString() {
return "Cat{" +
"weight=" + weight +
", height=" + height +
'}';
}
public Cat(Integer weight, Integer height) {
this.weight = weight;
this.height = height;
}
public Integer getWeight() {
return weight;
}
public Integer getHeight() {
return height;
}
/**
* 根据体重进行排序
* @param a
* @return
*/
@Override
public Integer comparateTo(Cat a) {
if (a.getWeight() > this.weight) return 1;
else if (a.getWeight() < this.weight) return -1;
return 0;
}
}
public interface Comparable<T> {
/**
* 比较方法
* @param t
* @return
*/
Integer comparateTo(T t);
}
让我们来给他们排序
- 使用简单的选择排序(拿一个值遍历所有的值排序)
- 根据实现 Comparable 对象的方法来进行排序(上面猫实现的是根据体重排序)
public class SortHandler{
public static void sort(Comparable[] arr){
for (int i = 0; i < arr.length-1; i++) {
int num = i;
for (int j = i+1; j < arr.length; j++) {
//根据传入对象的实现方法进行排序
num = arr[i].comparateTo(arr[j])>0?j:i;
}
//位置转换
swap(arr,i,num);
}
}
public static void swap(Comparable[] arr,Integer i ,Integer j){
Comparable com = arr[j];
arr[j] = arr[i];
arr[i] = com;
}
}
- 这是测试方法
- 创建三只猫 根据体重进行排序
public static void main(String[] args) {
Comparable[] arr = {new Cat(4,4),new Cat(1,1),new Cat(5,5)};
SortHandler.sort(arr);
System.out.println(Arrays.toString(arr));
}
万恶的产品来了,提要求让我们改成根据猫的身高来进行排序,这时可以:
-
改猫的代码.修改猫实现的 comparateTo 方法,改为根据身高排序
-
但是这样违背了设计模式的开闭原则
-
产品变更的内容只能是排序方面的,所以我们根据排序规则,需要优化一下代码
-
先指定一个规则接口
public interface Comparator<T> {
/**
* 比较对象
* @param t1
* @param t2
* @return
*/
Integer comparatorTo(T t1,T t2);
}
- 定义猫根据身高进行排序的规则
- 比较传入两只猫的身高,返回是否
public class CarHeightComparator implements Comparator<Cat>{
@Override
public Integer comparatorTo(Cat t1, Cat t2) {
if(t1.getHeight()>t2.getHeight()) return 1;
else if(t1.getHeight()<t2.getHeight()) return -1;
return 0;
}
}
- 定义一个通过排序接口实现类
- 入参: 比较对象集合 比较方法(根据身高/提供)
public class SortComparatorHandler<T>{
public void sort(T[] arr,Comparator<T> comparator){
for (int i = 0; i < arr.length-1; i++) {
int num = i;
for (int j = i+1; j < arr.length; j++) {
num = comparator.comparatorTo(arr[i],arr[j]) == -1?j:i;
}
//位置转换
swap(arr,i,num);
}
}
public void swap(T[] arr,Integer i ,Integer j){
T com = arr[j];
arr[j] = arr[i];
arr[i] = com;
}
}
- 测试方法
public static void main(String[] args) {
//通过策略模式 根据比较器的实现方法来进行比较
SortComparatorHandler sort = new SortComparatorHandler();
sort.sort(arr,new CarHeightComparator());
System.out.println(Arrays.toString(arr));
}
如果这样写的话,产品在需要改需求,我们不需要修改原代码,只需要重新提供一个根据新的排序规则方法的实现类,替换原先的排序规则就可以了
- 使用java8写法 一个方法里面只有一个方法,直接这么写
- SortComparatorHandler 这个方法里面的入参都要定义泛型(两个都要)
public static void main(String[] args) {
Cat[] arr = {new Cat(4,4),new Cat(1,1),new Cat(5,5)};
//通过策略模式 根据比较器的实现方法来进行比较
SortComparatorHandler<Cat> sort = new SortComparatorHandler<>();
sort.sort(arr, (t1,t2)->{
if(t1.getHeight()>t2.getHeight()) return 1;
else if(t1.getHeight()<t2.getHeight()) return -1;
return 0;
});
System.out.println(Arrays.toString(arr));
}