选择实现—简单工厂

  之前写了好多关于排序算法的文章,基本上都是总结性质的,其实排序算法的研究很细致,但是我的博客都基本上只是给出了大体的思路和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 A
16      *            int数组
17      * @param isInc
18      *            是否升序,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     @Override
11     public void sort(int[] A, boolean isInc) {
12         InsertSort(A, isInc);
13     }
14 
15     /**
16      * 插入排序算法
17      * 
18      * @param A
19      *            int数组
20      * @param isInc
21      *            是否升序,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     @Override
11     public void sort(int[] A, boolean isInc) {
12         mergeSort(A, 0, A.length - 1, isInc);
13     }
14 
15     /**
16      * 合并排序
17      * @param A
18      *            int数组
19      * @param p
20      *            起始位置
21      * @param r
22      *            终止位置
23      * @param isInc
24      *            是否升序,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 A
39      *            int数组
40      * @param p
41      *            起始位置
42      * @param q
43      *            中间位置
44      * @param r
45      *            终止位置
46      * @param isInc
47      *            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 index
101      *            以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.heapSize
114                     && 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 A
130      *            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 A
142      *            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     @Override
14     public void sort(int[] A) {
15         randomizedQuickSort(A, 1, A.length, true);
16     }
17 
18     @Override
19     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.InsertionSort
2 merge_sort = com.alfred.sort.MergeSort
3 heap_sort = com.alfred.sort.HeapSort
4 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 = SortFactory
18                 .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 = SortFactory
32                 .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 = SortFactory
46                 .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 = SortFactory
60                 .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

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

 

posted @ 2012-05-01 23:02  Mr. Coding  阅读(2000)  评论(2编辑  收藏  举报