zoukankan      html  css  js  c++  java
  • 选择实现—简单工厂

      之前写了好多关于排序算法的文章,基本上都是总结性质的,其实排序算法的研究很细致,但是我的博客都基本上只是给出了大体的思路和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

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

  • 相关阅读:
    hdoj5667 BestCoder Round #80 【费马小定理(膜拜)+矩阵快速幂+快速幂】
    几题LCS后的小总结
    uva12563
    hdoj1028;他们说这题叫dp...
    鉴于spfa基础上的差分约束算法
    BFS+PRIM
    优先队列(转载)【非常棒】
    BestCoder Round #73 (div.2)1002/hdoj5631
    zoj2412 dfs连通图
    dijkstra算法的应用(poj2387)+堆优化【还没学C艹很尴尬,不理解的先不写了,未完,待续...】
  • 原文地址:https://www.cnblogs.com/unpolishedgem/p/2478303.html
Copyright © 2011-2022 走看看