1 说明
在《设计模式-行为型设计模式》文章中的4.1、4.2章节(https://blog.csdn.net/weixin_37624828/article/details/106059837)已经提到策略模式和模板模式是如何编写的,并对应给出了两个例子,策略模式给出的两个数进行运算可以选择不同的算法,模板模式给出了一个游戏过程的执行顺序。
策略模式和模板模式在设计模式中都属于实现起来比较简单的,策略模式整体实现思想就是定义一个策略接口并定义该策略的诸多实现,然后将其封装至执行类中,定义执行方法,在编码时选择需要用到的策略执行即可;模板模式的实现思想一般是定义一个抽象类,定义一个方法确定其他抽象方法的执行顺序,然后由子类继承重写抽象方法来实现模板模式。
本文将运用模板模式和策略模式对比实现冒泡排序;
首先来个原版的冒泡排序
原版:
public static void bubbleSort(int[] array) {
for (int nextToLast = array.length - 2; nextToLast >= 0; nextToLast--) {
for (int index = 0; index <= nextToLast; index++) {
if (array[index] > array[index + 1]) {
int temp = array[index + 1];
array[index + 1] = array[index];
array[index] = temp;
}
}
}
}
为了可以应用模板模式,需要把这个方法给分解成更细小的方法。这里把if语句块的代码划分为更小粒度的方法,初步划分为比较方法(compareAndSwap)和交换方法(swap)。
拆分后:
public class BubbleSorter {
static int operations = 0;
public static int sort(int[] array) {
operations = 0;
if (array.length <= 1) {
return operations;
}
for (int nextToLast = array.length - 2; nextToLast >= 0; nextToLast--) {
for (int index = 0; index <= nextToLast; index++) {
compareAndSwap(array, index);
}
}
return operations;
}
private static void swap(int[] array, int index) {
int temp = array[index];
array[index] = array[index + 1];
array[index + 1] = temp;
}
private static void compareAndSwap(int[] array, int index){
if(array[index] > array[index + 1]) {
swap(array, index);
}
operations++;
}
}
2 模板模式实现冒泡排序的示例
根据上述分解就可以应用模板模式了。首先编写一个抽象类,将outOfOrder方法和swap方法抽象出来,然后再通过继承将上述两个方法进行重写即可。具体实现代码如下所示。
代码清单:
- BubbleSorter1.java
- IntBubbleSorter.java
- DoubleBubbleSorter.java
- TemplateDemo.java
1 BubbleSorter1.java
public abstract class BubbleSorter1 {
private int operations = 0;
protected int length = 0;
protected int doSort() {
operations = 0;
if (length <= 1) {
return operations;
}
for (int nextToLast = length - 2; nextToLast >= 0; nextToLast--) {
for (int index = 0; index <= nextToLast; index++) {
if (outOfOrder(index)) {
swap(index);
}
operations++;
}
}
return operations;
}
protected abstract void swap(int index);
protected abstract boolean outOfOrder(int index);
}
2 IntBubbleSorter.java
public class IntBubbleSorter extends BubbleSorter1 {
private int[] array = null;
public int bubbleSorter(int[] theArray) {
array = theArray;
length = array.length;
return doSort();
}
@Override
protected void swap(int index) {
int temp = array[index];
array[index] = array[index + 1];
array[index + 1] = temp;
}
@Override
protected boolean outOfOrder(int index) {
return (array[index] > array[index + 1]);
}
}
3 DoubleBubbleSorter.java
public class DoubleBubbleSorter extends BubbleSorter1 {
private double[] array = null;
public int bubbleSorter(double[] theArray) {
array = theArray;
length = array.length;
return doSort();
}
@Override
protected void swap(int index) {
double temp = array[index];
array[index] = array[index + 1];
array[index + 1] = temp;
}
@Override
protected boolean outOfOrder(int index) {
return (array[index] > array[index + 1]);
}
}
4 TemplateDemo.java
public class TemplateDemo {
public static void main(String[] args) {
int a[] = {2, 3, 6, 4, 0, 1, 7, 8, 5, 9};
double b[] = {2, 3, 6, 4, 0, 1, 7, 8, 5, 9};
IntBubbleSorter intBubbleSorter = new IntBubbleSorter();
DoubleBubbleSorter doubleBubbleSorter = new DoubleBubbleSorter();
intBubbleSorter.bubbleSorter(a);
doubleBubbleSorter.bubbleSorter(b);
toString1(a);
System.out.println();
toString2(b);
}
public static void toString1(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
System.out.print(" ");
;
}
}
public static void toString2(double[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
System.out.print(" ");
;
}
}
}
3 策略模式实现冒泡排序的示例
使用策略模式首先需要定义一个SortHandle的接口,主要来定义outOfOrder和swap方法。然后将这个策略封装至BubbleSorter2类中。
代码清单:
- SortHandle.java --接口
- IntSortHandle.java
- BubbleSorter2.java
- QuickBubbleSorter.java
- StrategyDemo.java
1 SortHandle.java
public interface SortHandle {
public void swap(int index);
public boolean outOfOrder(int index);
public int length();
public void setArray(Object array);
}
2 IntSortHandle.java
public class IntSortHandle implements SortHandle {
private int[] array = null;
@Override
public void swap(int index) {
int temp = array[index];
array[index] = array[index + 1];
array[index + 1] = temp;
}
@Override
public boolean outOfOrder(int index) {
return array[index] > array[index + 1];
}
@Override
public int length() {
return array.length;
}
@Override
public void setArray(Object array) {
this.array = (int[]) array;
}
}
3 BubbleSorter2.java
public class BubbleSorter2 {
private int operations = 0;
private int length = 0;
private SortHandle itsSortHandle = null;
public BubbleSorter2(SortHandle handle) {
itsSortHandle = handle;
}
public int sort(Object array) {
itsSortHandle.setArray(array);
length = itsSortHandle.length();
operations = 0;
if (length <= 1) {
return operations;
}
for (int nextToLast = length - 2; nextToLast >= 0; nextToLast--) {
for (int index = 0; index <= nextToLast; index++) {
if (itsSortHandle.outOfOrder(index)) {
itsSortHandle.swap(index);
}
operations++;
}
}
return operations;
}
}
4 QuickBubbleSorter.java
public class QuickBubbleSorter {
private int operations = 0;
private int length = 0;
private SortHandle itsSortHandle = null;
public QuickBubbleSorter(SortHandle handle) {
itsSortHandle = handle;
}
public int sort(Object array) {
itsSortHandle.setArray(array);
length = itsSortHandle.length();
operations = 0;
if (length <= 1) {
return operations;
}
boolean thisPassInOrder = false;
for (int nextToLast = length - 2; nextToLast >= 0 && !thisPassInOrder; nextToLast--) {
thisPassInOrder = true;
for (int index = 0; index <= nextToLast; index++) {
if (itsSortHandle.outOfOrder(index)) {
itsSortHandle.swap(index);
thisPassInOrder = false;
}
operations++;
}
}
return operations;
}
}
5 StrategyDemo.java
public class StrategyDemo {
public static void main(String[] args) {
int a[] = {2, 3, 6, 4, 0, 1, 7, 8, 5, 9};
BubbleSorter2 bubbleSorter2 = new BubbleSorter2(new IntSortHandle());
bubbleSorter2.sort(a);
toString(a);
System.out.println();
int b[] = {2, 3, 6, 4, 0, 1, 7, 8, 5, 9};
QuickBubbleSorter quickBubbleSorter = new QuickBubbleSorter(new IntSortHandle());
quickBubbleSorter.sort(b);
toString(b);
}
public static void toString(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(a[i]);
System.out.print(",");
}
}
}
4 结论
使用模板模式实现只允许一个通用的算法(在上述例子中指BubbleSorter1类中的doSort方法)来操纵多个可能的具体实现。策略模式完全遵循DIP原则,使用策略模式允许不同的算法(指BubbleSorter1中的sort方法,而且还可以重新定义一个新算法QuickBubbleSorter的sort方法)来操纵每个具体的实现。
模板模式和策略模式都可以用来分离高层算法和低层的具体实现。策略模式也允许具体实现细节完全独立于高层的算法,为高层算法的变动创造了便利,不过要以一些额外的复杂性、内存以及运行时间开销作为代价。