策略模式,即在多个对象有相同的操作的时候,我们可以通过使用策略模式来简化代码及扩展,这样遵循了开闭原则,以下以 排序 这个动作进行举例。另外设计模式大多都是多态的一张体现
具体策略模式有什么作用,以排序作为例子,假设现在我们需要对Cat进行排序,通常情况下我们只需要实现Comparator接口并重写compare方法即可实现排序,但是如果我们现在想使用多种排序方式,刚开始我们用Cat的重量进行排序,现在我们要根据身高排序,或者我们现在想要对Dog进行多种方式的排序
上面的举例有两个核心,待排序的对象数组、排序的方式
假设我们有一个Cat类
@Getter
@Setter
@ToString
@AllArgsConstructor
public class Cat {
/**
* 体重
*/
private Integer weight;
/**
* 身高
*/
private Integer height;
}
然后我们有一个排序类
package com.imysh.zmy.mca.designpattern.strategy;
import java.util.Comparator;
/**
* @author zhangmy
* @date 2022/6/25 8:06
* @description
*/
public class Sorter<T> {
/**
* 排序
* @param arr 待排序对象数组
* @param comparator 比较器
*/
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);
}
}
/**
* 内部方法 -- 交换顺序
* @param arr
* @param i
* @param j
*/
private void swap(T[] arr, int i, int j) {
T temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
Sorter类提供泛型T,意思是可以传不同的类,比如我们下面还会用到的Dog类
然后其中的sort方法支持实现了Comparator接口的比较
以上两点就解决了前面提到的两个核心
现在我们对Cat进行重量排序
Cat[] cats = {new Cat(1, 3), new Cat(5, 2), new Cat(2, 1)};
// 猫按重量排序
Sorter<Cat> catSorter1 = new Sorter<>();
catSorter1.sort(cats, (o1, o2) -> {
if (o1.getWeight() < o2.getWeight()) {
return -1;
} else if (o1.getWeight() > o2.getWeight()) {
return 1;
} else {
return 0;
}
});
System.out.println(Arrays.toString(cats));
我们将Cat对象数组和自定义的按weight比较的比较器传给sort方法
同样,比如我们想要通过height进行排序,我们可以照葫芦画瓢
// 猫按身高排序
Sorter<Cat> catSorter2 = new Sorter<>();
catSorter2.sort(cats, (o1, o2) -> {
if (o1.getHeight() < o2.getHeight()) {
return -1;
} else if (o1.getHeight() > o2.getHeight()) {
return 1;
} else {
return 0;
}
});
System.out.println(Arrays.toString(cats));
假设我们还有一个Dog类
@Getter
@Setter
@ToString
@AllArgsConstructor
public class Dog {
/**
* 饭量
*/
private Integer food;
/**
* 体长
*/
private Integer length;
}
同样我们可以按照food排序
Dog[] dogs = {new Dog(5, 2), new Dog(2, 3), new Dog(6, 5)};
// 狗按饭量排序
Sorter<Dog> dogSorter1 = new Sorter<>();
dogSorter1.sort(dogs, (o1, o2) -> {
if (o1.getFood() < o2.getFood()) {
return -1;
} else if (o1.getFood() > o2.getFood()) {
return 1;
} else {
return 0;
}
});
System.out.println(Arrays.toString(dogs));
也可以按照length排序
// 狗按体长排序
Sorter<Dog> dogSorter2 = new Sorter<>();
dogSorter2.sort(dogs, (o1, o2) -> {
if (o1.getLength() < o2.getLength()) {
return -1;
} else if (o1.getLength() > o2.getLength()) {
return 1;
} else {
return 0;
}
});
System.out.println(Arrays.toString(dogs));
综上,策略模式适用于在对多个对象进行相同的动作的时候,这样我们就可以将对象和动作提炼成参数,写成通用,动作一定写成接口,这样实现就可以有多种多样
像官方Collections.sort()就用到了策略模式
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
评论区