个人理解
我先把自己的结论放前面了,学习完策略模式,给我的感觉:
- 又加深了对java多态的理解,本质上策略模式就是java面对对象多态的实现
- 策略某种意义上,可以理解时选择语句if…else或者switch…case的变种,更加全面,适用性更强
本文举的例子参考jdk java.lang.Comparable接口
demo的目的:针对任意类型的arraylist的进行排序
本案例采用冒泡排序
//创建一个cat类
/**
* @Description: TODO
* @author: qinlei
* @date: 2020年06月10日 9:03
*/
public class Cat {
private int weight;
private int height;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public Cat() {
}
public Cat(int weight, int height, int age) {
this.weight = weight;
this.height = height;
this.age = age;
}
@Override
public String toString() {
return "Cat{" +
"weight=" + weight +
", height=" + height +
", age=" + age +
'}';
}
}
创建一个比较器的函数式接口
@FunctionalInterface
public interface Comparable<T> {
int compareTo(T t1,T t2);
}
创建一个Cat类的高度比较器实现比较器接口
/**
* @Description: 数值小的放前面
* @author: qinlei
* @date: 2020年06月10日 9:03
*/
public class CatHeightComparable implements Comparable<Cat>{
@Override
public int compareTo(Cat t1, Cat t2) {
if(t1.getHeight()<t2.getHeight()) return -1;
else if (t1.getHeight()>t2.getHeight()) return 1;
else return 0;
}
}
创建一个Cat类的宽度比较器实现比较器接口
/**
* @Description: 数值大的放前面
* @author: qinlei
* @date: 2020年06月10日 9:03
*/
public class CatWeightComparable implements Comparable<Cat>{
@Override
public int compareTo(Cat t1, Cat t2) {
if(t1.getWeight()<t2.getWeight()) return 1;
else if (t1.getWeight()>t2.getWeight()) return -1;
else return 0;
}
}
比较的方法
public void sort (ArrayList<T> list ,Comparable<T> comparable){
for (int i = 0; i < list.size(); i++) {
int min = i;
for (int j = i + 1;j<list.size();j++){
min = comparable.compareTo(list.get(j),list.get(min))==-1?j:min;
}
swap(list,i,min);
}
}
public void swap(ArrayList<T> t,int i, int j){
T temp = t.get(i);
t.set(i,t.get(j));
t.set(j,temp);
}
测试
public static void main(String[] args) {
ArrayList<Cat> cats = new ArrayList<>();
cats.add(new Cat(2,2,2));
cats.add(new Cat(1,1,1));
cats.add(new Cat(4,4,4));
System.out.println("排序前:"+cats);
SortDemo<Cat> sortDemo = new SortDemo<>();
//比较宽度
sortDemo.sort(cats,new CatWeightComparable());
System.out.println("按宽度排序后:"+cats);
//比较宽度
sortDemo.sort(cats,new CatHeightComparable());
System.out.println("按高度度排序后:"+cats);
}
细心的朋友可能发现了,所写的比较器接口有个注解@FunctionalInterface
- 该注解是jdk8以后的注解,表示该接口是个函数式接口.主要用于编译级错误检查,加上该注解,当你写的接口不符合函数式接口定义的时候,编译器会报错。
- 该接口中只能有一个抽象方法
- 这样的话就更方便了,因为可以使用lambda表达式了
例如
上述例子创建了高度比较器,宽度比较器
再将比较器实例化后传入sort()方法
使用lambda表达式的比较,不需要单独创建一个类实现Comparable比较器接口了
如:
public static void main(String[] args) {
ArrayList<Cat> cats = new ArrayList<>();
cats.add(new Cat(2, 2, 2));
cats.add(new Cat(1, 1, 1));
cats.add(new Cat(4, 4, 4));
System.out.println("排序前:" + cats);
SortDemo<Cat> sortDemo = new SortDemo<>();
//比较宽度
// sortDemo.sort(cats,new CatWeightComparable());
// System.out.println("按宽度排序后:"+cats);
//比较宽度
// sortDemo.sort(cats,new CatHeightComparable());
// System.out.println("按高度度排序后:"+cats);
//比较年龄
sortDemo.sort(cats, (t1, t2) -> {
if (t1.getAge() < t2.getAge()) {
return -1;
} else if (t1.getAge() > t2.getAge()) {
return 1;
} else {
return 0;
}
});
System.out.println("按年龄排序后:" + cats);
}
结果:
DEMO案例的总结
上述中的高度比较器(CatHeightComparable) 宽度比较器(CatWeightComparable) 还有使用lambda表达式实现的年龄比较
就是一个个的比较策略.整体就是一个策略模式.
应用场景
做地图服务时,不同的标记点有不同的图标样式,大小等等等
某个游戏,不同身份的用户(VIP,超VIP)他们的服饰等等豪华程度不同
简单来说,就是本来可以使用选择语句来实现的代码块,但是实现起来代码量重复量大且没有很高的可扩展性,不容易维护,这时就可以使用策略模式.
从这里就可以看出策略模式有这么两个优点:
-
可以把公共的代码移到父类里面,从而避免代码重复。
-
使用策略模式可以避免使用多重条件(if-else)语句。