作用
我们也有很多中方法来实现一个功能,但是我们需要一种简单、高效的方式来实现它,使得系统能够非常灵活,这就是策略模式。
策略模式其实很简单,就是针对不同的场景,做出不同的处理策略。将一系列行为封装起来,被封装起来的行为具有独立性外部不可改变其特性。
遵循了开闭原则,不需要改动旧代码,更方便维护。
使用方式
为了方便大家真正体会策略模式的好处,这里给出一系列的变换过程,方便大家对比。
实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Apple {
private String color;
private int weight;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Pear {
private String color;
private int weight;
}
ps:这里的注解使用了 lombok 。
实例化对象:
public static void main(String[] args) {
Apple[] apples = {new Apple("green", 13)
, new Apple("red", 16)
, new Apple("red", 20)};
Pear[] pears = {new Pear("green", 13)
, new Pear("yellow", 16)
, new Pear("yellow", 20)};
}
提出需求:输出apples中绿色的苹果,输出pears里面重量大于15的梨子。
public static void main(String[] args) {
~~~~~~~~~~~~~~~
compareColor(apples, "green");
compareWeight(pears, 15);
}
public static void compareColor(Apple[] apples, String color) {
for (Apple apple : apples) {
if (color.equals(apple.getColor())) {
System.out.println(apple);
}
}
}
public static void compareWeight(Pear[] pears, int weight) {
for (Pear pear : pears) {
if (pear.getWeight() > weight) {
System.out.println(pear);
}
}
}
ps:如果方法很多,我们一般是再封装一个方法,根据传的值,使用if … else if … else if …来调用下方进行筛选的方法。
public static <T> void compare(Object[] o, String s) {
if ("apple".equals(s)) compareColor((Apple[]) o, "green");
else if ("pear".equals(s)) compareWeight((Pear[]) o, 15);
}
上面这种方式很简单,但是他们的代码其实是冗余的,他们本质上都是对一个数组做一个筛选的行为。而且如果我们需要对很多不同的类做不同的筛选行为,那么我们就要创建很多不同的方法进行调用来满足我们的需求。
那我们能不能只用调用同一个方法,就可以满足我们的需求呢,这里我们就可以使用策略模式了。
分析:
- 第一个参数:我们应该能考虑到需要用一个能动态的接收不同类的关键字,这时候我们有两个选择:Object和泛型T。Object是所有类的父类,但是我们使用的时候还需要强制向下转型,所以我们选择泛型T会更方便。
- 第二个参数:本质上这个参数就是我们需要进行的行为(比如筛选颜色为绿色的苹果,筛选重量大于15的梨子),所以我们可以把这个行为提取成一个接口,然后根据不同的需求去实现这个接口。
总结:根据上面的的分析,我们现在需要一个接口,根据不同的需求来创建类并实现这个接口,创建一个统一的调用方法。
策略模式实现:
public static void main(String[] args) {
~~~~~~~~~~~~~~~
filter(apples, new ApplesGreenFilter());
filter(pears, new PearsWeightGt15Filter());
}
public static <T> void filter(T[] arr, Comparator comparator) {
for (T t : arr) {
if (comparator.comparator(t)) {
System.out.println(t);
}
}
}
public interface Comparator<T> {
boolean comparator(T t);
}
public static class ApplesGreenFilter implements Comparator<Apple> {
@Override
public boolean comparator(Apple apple) {
return "green".equals(apple.getColor());
}
}
public static class PearsWeightGt15Filter implements Comparator<Pear> {
@Override
public boolean comparator(Pear pear) {
return pear.getWeight() > 15;
}
}
当然java1.8的时候我们也可以使用lambda表达式来简化:
public static void main(String[] args) {
~~~~~~~~~~~~~~~
filter(apples, apple -> "green".equals(apple.getClass()));
filter(pears, pear -> pear.getWeight() > 15);
}
public static <T> void filter(T[] arr, Comparator comparator) {
for (T t : arr) {
if (comparator.comparator(t)) {
System.out.println(t);
}
}
}
public interface Comparator<T> {
boolean comparator(T t);
}
总结:
在策略模式中它将这些解决问题的方法定义成一个算法群,每一个方法都对应着一个具体的算法,这里的一个算法我就称之为一个策略。
虽然策略模式定义了算法,但是它并不提供算法的选择,即什么算法对于什么问题最合适这是策略模式所不关心的,所以对于策略的选择还是要客户来做。