一、简介
1.1 模式定义
定义一系列算法将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为政策模式。策略模式是一种对象行为型模式。
1.2 适用场景
1)如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对在许多行为中选择一种行为。
2)一个系统需要动态地在几种算法中选择一种,那么可以将这些算法封装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类并只需要维持一个数据类型是抽象算法类的对象。
3)如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并且体现面向对象设计的概念。
4)不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法和相关数据结构,提高算法的保密性与安全性。
1.3 优点
1)策略模式提供了对“开闭原则”的完美支持,用户可以在不修改原有系统的基础上选择算法或行为,也可以灵活地增加新的算法或行为。
2)策略模式提供了管理先关的算法族的办法。策略类的等级结构定义了一个算法或行为族,恰当使用继承可以把公共的代码移到父类里面,从而避免重复的代码。
3)策略模式提供了可以替换继承关系的办法,继承可以处理多种算法或行为,如果不使用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用就和算法或行为本身混在一起,不符合“单一职责”,决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为本身的逻辑混合在一起,从而不可能再独立演化,而且使用继承无法实现算法或行为的动态改变。
4)使用策略模式可以避免使用多重条件语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件转移语句里面,比使用继承的办法还要原始落后。
1.4 缺点
1)客户端必须知道所有的策略类,并自行决定使用哪一个策略类。者意味着客户端必须理解这些算法的区别,一便适时选择恰当的算法类。换言之,策略模式只使用与客户端直达所有的算法或行为的情况。
2)策略模式将造成产生很多策略类和对象,可以通过使用享元模式在一定程度上减少对象的数量。
二、示例:策略模式
2.1 结构图
2.2 抽象排序类Sort(抽象排序类)
public interface Sort {
public int[] sort(int[] arr);
}
2.3 具体策略类BubbleSort(冒泡排序)
public class BubbleSort implements Sort{
/**
* 冒泡排序
*/
@Override
public int[] sort(int[] arr) {
int len = arr.length;
for (int i = 0; i < len; i++) {
for (int j = i+1; j < len; j++) {
int temp;
if (arr[i] > arr[j]) {
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
System.out.println("冒泡算法!");
return arr;
}
}
2.4 具体策略类SelectionSort(选择排序)
public class SelectionSort implements Sort{
/**
* 选择排序
*/
@Override
public int[] sort(int[] arr) {
int len = arr.length;
int temp;
for (int i = 0; i < len; i++) {
temp = arr[i];
int j;
int samllestLocation = i;
for (j = i+1; j < len; j++) {
if (arr[j] < temp) {
temp = arr[j];
samllestLocation = j;
}
}
arr[samllestLocation] = arr[i];
arr[i] = temp;
}
System.out.println("选择排序");
return arr;
}
}
2.5 具体策略类InsertionSort(插入排序)
public class InsertionSort implements Sort{
/**
* 插入排序
*/
@Override
public int[] sort(int[] arr) {
int len = arr.length;
for (int i = 1; i < len; i++) {
int j;
int temp = arr[i];
for (j = i; j > 0; j--) {
if (arr[j-1] > temp) {
arr[j] = arr[j-1];
} else {
break;
}
}
arr[j] = temp;
}
System.out.println("插入排序");
return arr;
}
}
2.6 环境类ArrayHandler(数组处理类)
public class ArrayHandler {
private Sort sortObj;
public int[] sort(int[] arr) {
sortObj.sort(arr);
return arr;
}
public void setSortObj(Sort sortObj) {
this.sortObj = sortObj;
}
}
2.7 客户端测试Demo类
public class Demo {
public static void main(String[] args) {
int[] arr = {9,8,7,6,5,4,3,2,1,11};
ArrayHandler arrayHandler = new ArrayHandler();
arrayHandler.setSortObj(new InsertionSort());
System.out.println(Arrays.toString(arrayHandler.sort(arr)));
}
}