定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
假设需求是做数组排序,但是需求方并没有想好用哪种算法,为了应对自如,我们先写好冒泡、归并和快速三种算法,并且通过设计模式让客户端可以随意替换。
UML图:
代码:
public interface Sorter {
void sort(int[] numbers);
}
public class BubbleSorter implements Sorter {
@Override
public void sort(int[] numbers) {
if(numbers == null) return;
for(int i = 0; i < numbers.length; i++) {
for(int j = i + 1; j < numbers.length; j++) {
if(numbers[i] > numbers[j]) {
int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
}
}
System.out.println("冒泡排序: " + Arrays.toString(numbers));
}
}
import java.util.Arrays;
public class MergeSorter implements Sorter {
@Override
public void sort(int[] numbers) {
if(numbers == null) return;
mergeSort(numbers, 0, numbers.length - 1);
System.out.println("归并排序: " + Arrays.toString(numbers));
}
public void mergeSort(int[] numbers, int from, int to) {
int middle = (from + to) / 2;
if (from < to) {
mergeSort(numbers, from, middle);
mergeSort(numbers, middle + 1, to);
if(numbers[middle] < numbers[middle + 1])
return;
merge(numbers, from, middle, to);
}
}
private void merge(int[] numbers, int from, int middle, int to) {
int[] temp = new int[to - from + 1];
int left = from;
int right = middle + 1;
int i = 0;
while (left <= middle && right <= to) {
if (numbers[left] < numbers[right]) {
temp[i++] = numbers[left++];
} else {
temp[i++] = numbers[right++];
}
}
while (left <= middle) {
temp[i++] = numbers[left++];
}
while (right <= to) {
temp[i++] = numbers[right++];
}
System.arraycopy(temp, 0, numbers, from, temp.length);
}
}
import java.util.Arrays;
public class QuickSorter implements Sorter {
@Override
public void sort(int[] numbers) {
if(numbers == null) return;
sort(numbers, 0, numbers.length - 1);
System.out.println("快速排序: " + Arrays.toString(numbers));
}
public void sort(int[] numbers, int left, int right) {
if(left >= right) {
return;
}
int temp = numbers[left];
int t;
int i = left;
int j = right;
while(i != j) {
while (numbers[j] >= temp && i < j)
j--;
while (numbers[i] <= temp && i < j)
i++;
if(i < j) {
t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
}
numbers[left] = numbers[i];
numbers[i] = temp;
sort(numbers, left, i - 1);
sort(numbers, i + 1, right);
}
}
客户端:
public class Context {
private Sorter sorter;
public Context(Sorter sorter) {
this.sorter = sorter;
}
public void sort(int[] numbers) {
this.sorter.sort(numbers);
}
public static void main(String[] args) {
int[] numbers = new int[] { 7, 3, 5, 8, 1, 9, 4, 5, 6, 2, 10};
Context context = new Context(new BubbleSorter());
context.sort(numbers);
context = new Context(new MergeSorter());
context.sort(numbers);
context = new Context(new QuickSorter());
context.sort(numbers);
}
}
策略模式和工厂模式看起来很接近,如果把客户端拟人化并且从客户端的角度考虑,那么策略模式下,对采用了哪个算法、结果如何是关注的;而工厂模式下,客户端只是把工作分配下去,具体工厂做了什么、结果如何并不关心。
举例来说:
1 老板:X项目是重点项目,去准备5个方案,我来评估。
其中,老板即为客户端,需要明确知道方案的存在、执行细节,才能做出选择,此为策略模式。
2 老板:X项目是重点项目,多准备几套方案,务必要做好。
工厂模式下,老板并不需要知道具体几套方案、什么内容,只要把任务交给“工厂”这个角色就可以了。