选择实现—简单工厂

来源:互联网 发布:小说朗读软件 编辑:程序博客网 时间:2024/04/25 03:50

  之前写了好多关于排序算法的文章,基本上都是总结性质的,其实排序算法的研究很细致,但是我的博客都基本上只是给出了大体的思路和Java程序实现,算法写起来比较繁琐,感兴趣的话,自己去研究下吧,我推荐算法导论这本书。

  看到这么多的排序算法,如果要将其真正用到Java程序里边的话,未免也太复杂了,因为要为每一种算法在使用之前都要先创建一个实例,然后才能使用,这样就暴露了实现,不符合面向对象的基本要求,因此建立一个工厂类,然后让工厂来负责具体的算法的创建,客户端程序员就不必知道具体的算法了,而且,这样做就可以统一接口。

  简单工厂的本质是:封装实现

  需要注意的是简单工厂的重点在于选择,实现是已经做好了的。简单工厂的目的为在于客户端来选择相应的实现,从而使得客户端和实现之间的解耦。这样一来,具体的实现,就不用变动客户端的代码了,这个变化会被简单工厂吸收和屏蔽。

  使用我之前写过的算法的例子,可以这样来应用简单工厂模式。

  首先,建立一个具体算法的接口,实现面向接口的编程。接口定义如下:

  

SortAlgorithm.java
 1 package com.alfred.sort; 2  3 public interface SortAlgorithm { 4     /** 5      * 将数组按照升序排序 6      *  7      * @param A 8      *            int数组,按升序排列 9      */10     public void sort(int[] A);11 12     /**13      * 将数组按照升序或降序排序14      * 15      * @param A16      *            int数组17      * @param isInc18      *            是否升序,true为升序,false为降序19      */20     public void sort(int[] A, boolean isInc);21 }

  然后,建立每一个算法的具体实现,每一个算法都要实现这个接口。

  

InsertionSort.java
 1 package com.alfred.sort; 2  3 public class InsertionSort implements SortAlgorithm { 4      5     @Override 6     public void sort(int[] A) { 7         InsertSort(A, true); 8     } 9 10     @Override11     public void sort(int[] A, boolean isInc) {12         InsertSort(A, isInc);13     }14 15     /**16      * 插入排序算法17      * 18      * @param A19      *            int数组20      * @param isInc21      *            是否升序,true为升序,false为降序22      */23     private void InsertSort(int[] A, boolean isInc) {24         int len = A.length;25         int key = 0;26         int i = 0;27         for (int j = 1; j < len; j++) {28             key = A[j];29             i = j - 1;30             while (i >= 0 && (isInc ? A[i] > key : A[i] < key)) {31                 A[i + 1] = A[i];32                 i = i - 1;33             }34             A[i + 1] = key;35         }36     }37 }
MergeSort.java
 1 package com.alfred.sort; 2  3 public class MergeSort implements SortAlgorithm { 4  5     @Override 6     public void sort(int[] A) { 7         mergeSort(A, 0, A.length - 1, true); 8     } 9 10     @Override11     public void sort(int[] A, boolean isInc) {12         mergeSort(A, 0, A.length - 1, isInc);13     }14 15     /**16      * 合并排序17      * @param A18      *            int数组19      * @param p20      *            起始位置21      * @param r22      *            终止位置23      * @param isInc24      *            是否升序,true为升序,false为降序25      */26     private void mergeSort(int[] A, int p, int r, boolean isInc) {27         int q = 0;28         if (p < r) {29             q = (p + r) / 2;30             mergeSort(A, p, q, isInc);31             mergeSort(A, q + 1, r, isInc);32             merge(A, p, q, r, isInc);33         }34     }35 36     /**37      * 合并两个排好的序列38      * @param A39      *            int数组40      * @param p41      *            起始位置42      * @param q43      *            中间位置44      * @param r45      *            终止位置46      * @param isInc47      *            isInc 是否升序,true为升序,false为降序48      */49     private void merge(int[] A, int p, int q, int r, boolean isInc) {50         int nLeft = q - p + 1;51         int nRight = r - q;52         int[] left = new int[nLeft];53         int[] right = new int[nRight];54         int i = 0, j = 0, k = 0;55         for (i = 0; i < nLeft; i++) {56             left[i] = A[p + i];57         }58         for (j = 0; j < nRight; j++) {59             right[j] = A[q + j + 1];60         }61         i = 0;62         j = 0;63         for (k = p; k <= r; k++) {64             if (isInc ^ (left[i] <= right[j])) {65                 A[k] = right[j];66                 j++;67             } else {68                 A[k] = left[i];69                 i++;70             }71 72             if (i == nLeft) {73                 k++;74                 for (; j < nRight; j++) {75                     A[k] = right[j];76                     k++;77                 }78             }79             if (j == nRight) {80                 k++;81                 for (; i < nLeft; i++) {82                     A[k] = left[i];83                     k++;84                 }85             }86         }87     }88 }
HeapSort.java
  1 package com.alfred.sort;  2   3 public class HeapSort implements SortAlgorithm {  4   5     private IntArray A = null;  6   7     public HeapSort() {  8         A = new IntArray();  9     } 10  11     private class IntArray { 12         public int[] aArray = null; 13         public int heapSize = 0; 14     } 15  16     @Override 17     public void sort(int[] A) { 18         maxHeapSort(A); 19     } 20  21     @Override 22     public void sort(int[] A, boolean isInc) { 23         if (isInc) { 24             maxHeapSort(A); 25         } else { 26             minHeapSort(A); 27         } 28     } 29  30     /** 31      * 最大堆排序,升序 32      *  33      * @param A 34      *            int数组 35      */ 36     private void maxHeapSort(int[] A) { 37         this.A.aArray = A; 38         this.A.heapSize = A.length; 39         buildMaxHeap(this.A); 40         for (int i = A.length; i >= 2; i--) { 41             exchange(1, i); 42             this.A.heapSize = this.A.heapSize - 1; 43             maxHeapify(this.A, 1); 44         } 45     } 46  47     /** 48      * 最小堆排序,降序 49      *  50      * @param A 51      *            int数组 52      */ 53     private void minHeapSort(int[] A) { 54         this.A.aArray = A; 55         this.A.heapSize = A.length; 56         buildMinHeap(this.A); 57         for (int i = A.length; i >= 2; i--) { 58             exchange(1, i); 59             this.A.heapSize = this.A.heapSize - 1; 60             minHeapify(this.A, 1); 61         } 62     } 63  64     /** 65      * 使得以index为根的子树成为最大堆 66      *  67      * @param A 68      *            int数组 69      * @param index 70      *            以index为根,从1开始 71      */ 72     private void maxHeapify(IntArray A, int index) { 73         while (index < A.heapSize / 2 + 1) { 74             int left = left(index); 75             int right = right(index); 76             int largest = 0; 77             if (left <= A.heapSize && A.aArray[left - 1] > A.aArray[index - 1]) { 78                 largest = left; 79             } else { 80                 largest = index; 81             } 82             if (right <= A.heapSize 83                     && A.aArray[right - 1] > A.aArray[largest - 1]) { 84                 largest = right; 85             } 86             if (index != largest) { 87                 exchange(index, largest); 88                 index = largest; 89             } else { 90                 index = A.heapSize / 2 + 1; 91             } 92         } 93     } 94  95     /** 96      * 使得以index为根的子树成为最小堆 97      *  98      * @param A 99      *            int数组100      * @param index101      *            以index为根,从1开始102      */103     private void minHeapify(IntArray A, int index) {104         while (index < A.heapSize / 2 + 1) {105             int left = left(index);106             int right = right(index);107             int smallest = 0;108             if (left <= A.heapSize && A.aArray[left - 1] < A.aArray[index - 1]) {109                 smallest = left;110             } else {111                 smallest = index;112             }113             if (right <= A.heapSize114                     && A.aArray[right - 1] < A.aArray[smallest - 1]) {115                 smallest = right;116             }117             if (index != smallest) {118                 exchange(index, smallest);119                 index = smallest;120             } else {121                 index = A.heapSize / 2 + 1;122             }123         }124     }125 126     /**127      * 建最大堆128      * 129      * @param A130      *            int数组131      */132     private void buildMaxHeap(IntArray A) {133         for (int i = A.aArray.length / 2; i >= 1; i--) {134             maxHeapify(A, i);135         }136     }137 138     /**139      * 建最小堆140      * 141      * @param A142      *            int数组143      */144     private void buildMinHeap(IntArray A) {145         for (int i = A.aArray.length / 2; i >= 1; i--) {146             minHeapify(A, i);147         }148     }149 150     private int left(int index) {151         return 2 * index;152     }153 154     private int right(int index) {155         return 2 * index + 1;156     }157 158     private void exchange(int i, int j) {159         int temp = A.aArray[i - 1];160         A.aArray[i - 1] = A.aArray[j - 1];161         A.aArray[j - 1] = temp;162     }163 164 }
QuickSort.java
 1 package com.alfred.sort; 2  3 import java.util.Random; 4  5 public class QuickSort implements SortAlgorithm { 6  7     private Random rand = null; 8  9     public QuickSort() {10         rand = new Random();11     }12 13     @Override14     public void sort(int[] A) {15         randomizedQuickSort(A, 1, A.length, true);16     }17 18     @Override19     public void sort(int[] A, boolean isInc) {20         randomizedQuickSort(A, 1, A.length, isInc);21     }22     23     /**24      * 随机化的快速排序25      * @param A 要排序的int数组26      * @param p 起始位置27      * @param r 终止位置28      * @param isInc 是否升序,true为升序,false为降序29      */30     private void randomizedQuickSort(int[] A, int p, int r, boolean isInc) {31         if (p < r) {32             int q = randomizedPartition(A, p, r, isInc);33             randomizedQuickSort(A, p, q - 1, isInc);34             randomizedQuickSort(A, q + 1, r, isInc);35         }36     }37     38     /**39      * 随机化的对数组的划分40      * @param A 要划分的int数组41      * @param p 起始位置42      * @param r 终止位置43      * @param isInc 是否升序,true为升序,false为降序44      * @return 划分数组的下标45      */46     private int randomizedPartition(int[] A, int p, int r, boolean isInc) {47         int i = rand.nextInt(r - p);48         exchange(A, r, i + p);49         return partition(A, p, r, isInc);50     }51     52     /**53      * 对数组进行划分54      * @param A 要划分的int数组55      * @param p 起始位置56      * @param r 终止位置57      * @param isInc 是否升序,true为升序,false为降序58      * @return 划分数组的下标59      */60     private int partition(int[] A, int p, int r, boolean isInc) {61         int x = A[r - 1];62         int i = p - 1;63         for (int j = p; j <= r - 1; j++) {64             if (isInc ? A[j - 1] <= x : A[j - 1] >= x) {65                 i++;66                 exchange(A, i, j);67             }68         }69         exchange(A, i + 1, r);70         return i + 1;71     }72 73     private void exchange(int[] A, int i, int j) {74         int temp = A[i - 1];75         A[i - 1] = A[j - 1];76         A[j - 1] = temp;77     }78 }

  接下来,建立一个工厂类来为客户端选择具体的算法实现。

SortFactory.java
 1 package com.alfred.sort; 2  3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.Properties; 6  7 public class SortFactory { 8  9     public static SortAlgorithm getSortAlgorithm(String type) {10         11         Properties prop = new Properties();12         InputStream in = null;13         14         try{15             in = SortFactory.class.getResourceAsStream("FactoryConfig.properties");16             prop.load(in);17         }catch(IOException e){18             System.out.println("装载配置文件出错,具体的堆栈信息如下:");19             e.printStackTrace();20         }finally{21             try{22                 in.close();23             }catch(IOException e){24                 e.printStackTrace();25             }26         }27         28         SortAlgorithm sortAlgorithm = null;29         try{30             sortAlgorithm = (SortAlgorithm)Class.forName(prop.getProperty(type)).newInstance();31         }catch(InstantiationException e){32             e.printStackTrace();33         }catch(IllegalAccessException e){34             e.printStackTrace();35         }catch(ClassNotFoundException e){36             e.printStackTrace();37         }38         return sortAlgorithm;39     }40 41     private SortFactory() {42 43     }44 }

  其中反射用的配置文件如下:

FactoryConfig.properties
1 insert_sort = com.alfred.sort.InsertionSort2 merge_sort = com.alfred.sort.MergeSort3 heap_sort = com.alfred.sort.HeapSort4 quick_sort = com.alfred.sort.QuickSort

  当然,还有之前简化的打印类:

Print.java
 1 package com.alfred.sort; 2  3 public class Print { 4     public static void print() { 5         System.out.println(); 6     } 7  8     public static void print(boolean x) { 9         System.out.println(x);10     }11 12     public static void print(char x) {13         System.out.println(x);14     }15 16     public static void print(char[] x) {17         System.out.println(x);18     }19 20     public static void print(double x) {21         System.out.println(x);22     }23 24     public static void print(float x) {25         System.out.println(x);26     }27 28     public static void print(int x) {29         System.out.println(x);30     }31 32     public static void print(long x) {33         System.out.println(x);34     }35 36     public static void print(Object x) {37         System.out.println(x);38     }39 40     public static void print(String x) {41         System.out.println(x);42     }43 44     private Print() {45 46     }47 }

  还有定义算法名称的常量类:

AlgorithmConstants.java
 1 package com.alfred.sort; 2  3 public class AlgorithmConstants { 4  5     public static final String INSERT_SORT = "insert_sort"; 6     public static final String MERGE_SORT = "merge_sort"; 7     public static final String HEAP_SORT = "heap_sort"; 8     public static final String QUICK_SORT = "quick_sort"; 9 10     private AlgorithmConstants() {11 12     }13 }

  最后,来写一个测试类来测试一下吧!

SortMain.java
 1 package com.alfred.sort; 2  3 import static com.alfred.sort.Print.print; 4  5 public class SortMain { 6  7     public static void main(String[] args) { 8          9         int[] A = new int[] { 23, 45, 36, 78, 45, 16, 59, 62, 569 };10         int[] aCopy = null;11         print("原始数组:");12         printIntArray(A);13         14         /**********************15          * 插入排序16          *********************/17         SortAlgorithm insertSort = SortFactory18                 .getSortAlgorithm(AlgorithmConstants.INSERT_SORT);19         print("插入排序,升序排列:");20         aCopy = A.clone();21         insertSort.sort(aCopy);22         printIntArray(aCopy);23         print("插入排序,降序排列:");24         aCopy = A.clone();25         insertSort.sort(aCopy, false);26         printIntArray(aCopy);27         28         /**********************29          * 合并排序30          *********************/31         SortAlgorithm mergeSort = SortFactory32                 .getSortAlgorithm(AlgorithmConstants.MERGE_SORT);33         print("合并排序,升序排列:");34         aCopy = A.clone();35         mergeSort.sort(aCopy);36         printIntArray(aCopy);37         print("合并排序,降序排列:");38         aCopy = A.clone();39         mergeSort.sort(aCopy, false);40         printIntArray(aCopy);41         42         /**********************43          * 堆排序44          *********************/45         SortAlgorithm heapSort = SortFactory46                 .getSortAlgorithm(AlgorithmConstants.HEAP_SORT);47         print("最大堆排序,升序排列:");48         aCopy = A.clone();49         heapSort.sort(aCopy);50         printIntArray(aCopy);51         print("最小堆排序,降序排列:");52         aCopy = A.clone();53         heapSort.sort(aCopy, false);54         printIntArray(aCopy);55 56         /**********************57          * 快速排序58          *********************/59         SortAlgorithm quickSort = SortFactory60                 .getSortAlgorithm(AlgorithmConstants.QUICK_SORT);61         print("快速排序,升序排列:");62         aCopy = A.clone();63         quickSort.sort(aCopy);64         printIntArray(aCopy);65         print("快速排序,降序排列:");66         aCopy = A.clone();67         quickSort.sort(aCopy, false);68         printIntArray(aCopy);69 70     }71     72     private static void printIntArray(int[] A){73         int row = A.length / 10 + 1;74         int index = 0;75         for(int i = 0; i < row; i++){76             for(int j = 0; j < 10; j++){77                 index = i * 10 + j;78                 if(index >= A.length){79                     break;80                 }else{81                     boolean x = (index + 1) % 10 == 0 || index == A.length - 1;82                     if(x){83                         System.out.print(A[index]);84                     }else{85                         System.out.print(A[index] + ",");86                     }87                 }88             }89         }90         print();91     }92 }

  输出为:

  原始数组:
  23,45,36,78,45,16,59,62,569
  插入排序,升序排列:
  16,23,36,45,45,59,62,78,569
  插入排序,降序排列:
  569,78,62,59,45,45,36,23,16
  合并排序,升序排列:
  16,23,36,45,45,59,62,78,569
  合并排序,降序排列:
  569,78,62,59,45,45,36,23,16
  最大堆排序,升序排列:
  16,23,36,45,45,59,62,78,569
  最小堆排序,降序排列:
  569,78,62,59,45,45,36,23,16
  快速排序,升序排列:
  16,23,36,45,45,59,62,78,569
  快速排序,降序排列:
  569,78,62,59,45,45,36,23,16

  从这个结果可以看出,所有的算法都能完成排序的工作,而且用了简单工厂模式之后,客户端程序就再也不需要知道具体的排序算法的实现了。