策略模式定义了一系列算法,封装了这些算法,并使它们可以互换;
策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化
注:基于面向对象的特性:多态;
1.实现类图- context : 运行特定策略的类;
- ConcreteStrategy1 ,ConcreteStrategy2,ConcreteStrategy3 具体的策略实现
- Strategy: 抽象的策略;
public interface Strategy {
void algorithm();
}
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void invokeAlgorithm() {
strategy.algorithm();
}
}
public class ConcreteStrategy1 implements Strategy{
@Override
public void algorithm() {
System.out.println("1111111111");
}
}
public class ConcreteStrategy2 implements Strategy {
@Override
public void algorithm() {
System.out.println("222222222");
}
}
public class ConcreteStrategy1 implements Strategy{
@Override
public void algorithm() {
System.out.println("1111111111");
}
}
可以看到 是 实现是 基于面向对象的特性:多态;
3.JDK 的实现Collections public staticvoid sort(List list, Comparator super T> c)
集合的工具类对List 安装指定的比较器(可以看做是Strategy 的实现)排序
4.模拟JDK 的实现场景:对类 Rectangle Square 按照属性排序
4.1 第一版public class Rectangle {
int width;
int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public String toString() {
return "Rectangle{" + "width=" + width + ", height=" + height + '}';
}
}
public class Square {
int length;
public Square(int length) {
this.length = length;
}
@Override
public String toString() {
return "Square{" + "length=" + length + '}';
}
}
一般做法就是 写两个工具类分别对这两个类属性做判断 并且排序 如下
// 对 Rectangle 按照 width 排序
public static void sort(Rectangle[] arr) {
for (int i = 0; i < arr.length; i++) {
int min = i;
for (int j = i + 1; j < arr.length; j++) {
min = arr[j].width - arr[min].width < 0 ? j : min;
}
Rectangle temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
//对 Square 按照 length 排序
public static void sort(Square[] arr) {
for (int i = 0; i < arr.length; i++) {
int min = i;
for (int j = i + 1; j < arr.length; j++) {
min = arr[j].length - arr[min].length < 0 ? j : min;
}
Square temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
可以看到是相对冗余代码比较多 ,只有一部分是不同的,当然可以简化下 如下
4.2 第二版抽取一个属性对比方法 ,
public interface ShapeComparable{ int compare(T o1); }
public class Rectangle implements ShapeComparable{ ..... //添加方法 @Override public int compare(Rectangle o1) { return this.width - o1.width; } } public class Square implements ShapeComparable { ..... //添加方法 @Override public int compare(Square o1) { return this.length - o1.length; } }
修改后 sort 方法就可以简化为一个方法
public class SortUtil {
public static void sort(ShapeComparator[] arr) {
for (int i = 0; i < arr.length; i++) {
int min = i;
for (int j = i + 1; j < arr.length; j++) {
min = arr[j].compare(arr[min]) < 0 ? j : min;
}
ShapeComparator temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
}
排序方法简化成一个,很简化了,排序的时候都调用compare , 来判断大小
问题: Rectangle 的另一个字段比较怎么办? 修改 compare 方法的代码? ,两个比较都想要怎么处理;
最好是不要修改原来 compare 的代码 (对修改关闭,对扩展开发 原则)
所以上面的设计并不是最好的设计!
4.3 第三版Rectangle 和 Square 保持和第一版一样不变
新增 ShapeComparator 比较器接口 ,可以看做是策略(Strategy )的抽象类
public interface ShapeComparator{ int compareTo(T o1, T o2); }
//比较方法修改,排序的时候,执行自定义的排序策略
public class SortUtil {
public static void sort(T[] arr, ShapeComparator shapeComparator) {
for (int i = 0; i < arr.length; i++) {
int min = i;
for (int j = i + 1; j < arr.length; j++) {
min = shapeComparator.compareTo(arr[j], arr[min]) < 0 ? j : min;
}
T temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
}
}
我们自定义的比较器,可以是任意扩展的,这样对 类的排序就很灵活,扩展性也有很大的提高;
示例: 两个比较器都是 对 Rectangle 的排序,这个可以无线扩展,规则可以任意制定;
public class RectangleComparator1 implements ShapeComparator{ @Override public int compareTo(Rectangle o1, Rectangle o2) { return o1.width - o2.width; } } public class RectangleComparator2 implements ShapeComparator { @Override public int compareTo(Rectangle o1, Rectangle o2) { return o1.height - o2.height; } }
public static void main(String[] args) {
Rectangle rectangle = new Rectangle(2344, 1);
Rectangle rectangle1 = new Rectangle(23423, 9);
Rectangle rectangle2 = new Rectangle(65756, 8);
Rectangle rectangle3 = new Rectangle(544, 7);
Rectangle arr[] = { rectangle, rectangle1, rectangle2, rectangle3 };
SortUtil.sort(arr, new RectangleComparator1());
for (Rectangle rectangle4 : arr) {
System.out.println(rectangle4);
}
SortUtil.sort(arr, new RectangleComparator2());
for (Rectangle rectangle5 : arr) {
System.out.println(rectangle5);
}
}
4.4 总结
模拟JDK Collections.sort() ,JDK 中这个方法可以根据使用者自定义的策略对List 内容排序;排序规则可以任意指定,可扩展性非常高;只需要自己指定是如何比较;
注 :我们编写的 ShapeComparator和 JDK 的 Comparator接口 类似;
第三版的ShapeComparator 接口JDK 也有,Collections.sort() 不指定Comparator 就会走对象的实现的Comparable接口;
public static> void sort(List list)



