关闭

不兼容结构的协调——适配器模式(二)

标签: 适配器模式
303人阅读 评论(0) 收藏 举报
分类:

3 完整解决方案

      Sunny软件公司开发人员决定使用适配器模式来重用算法库中的算法,其基本结构如图9-4所示:

9-4  算法库重用结构图

       在图9-4中,ScoreOperation接口充当抽象目标,QuickSortBinarySearch类充当适配者,OperationAdapter充当适配器。完整代码如下所示:

  1. //抽象成绩操作类:目标接口  
  2. interface ScoreOperation {  
  3.     public int[] sort(int array[]); //成绩排序  
  4.     public int search(int array[],int key); //成绩查找  
  5. }  
  6.   
  7. //快速排序类:适配者  
  8. class QuickSort {  
  9.     public int[] quickSort(int array[]) {  
  10.         sort(array,0,array.length-1);  
  11.         return array;  
  12.     }  
  13.   
  14.     public void sort(int array[],int p, int r) {  
  15.         int q=0;  
  16.         if(p<r) {  
  17.             q=partition(array,p,r);  
  18.             sort(array,p,q-1);  
  19.             sort(array,q+1,r);  
  20.         }  
  21.     }  
  22.   
  23.     public int partition(int[] a, int p, int r) {  
  24.         int x=a[r];  
  25.         int j=p-1;  
  26.         for (int i=p;i<=r-1;i++) {  
  27.             if (a[i]<=x) {  
  28.                 j++;  
  29.                 swap(a,j,i);  
  30.             }  
  31.         }  
  32.         swap(a,j+1,r);  
  33.         return j+1;   
  34.     }  
  35.   
  36.     public void swap(int[] a, int i, int j) {     
  37.         int t = a[i];     
  38.         a[i] = a[j];     
  39.         a[j] = t;     
  40.     }  
  41. }  
  42.   
  43. //二分查找类:适配者  
  44. class BinarySearch {  
  45.     public int binarySearch(int array[],int key) {  
  46.         int low = 0;  
  47.         int high = array.length -1;  
  48.         while(low <= high) {  
  49.             int mid = (low + high) / 2;  
  50.             int midVal = array[mid];  
  51.             if(midVal < key) {    
  52.                low = mid +1;    
  53.             }  
  54.             else if (midVal > key) {    
  55.                 high = mid -1;    
  56.             }  
  57.             else {    
  58.                 return 1//找到元素返回1    
  59.            }  
  60.         }  
  61.         return -1;  //未找到元素返回-1  
  62.     }  
  63. }  
  64.   
  65. //操作适配器:适配器  
  66. class OperationAdapter implements ScoreOperation {  
  67.     private QuickSort sortObj; //定义适配者QuickSort对象  
  68.     private BinarySearch searchObj; //定义适配者BinarySearch对象  
  69.   
  70.     public OperationAdapter() {  
  71.         sortObj = new QuickSort();  
  72.         searchObj = new BinarySearch();  
  73.     }  
  74.   
  75.     public int[] sort(int array[]) {    
  76.        return sortObj.quickSort(array); //调用适配者类QuickSort的排序方法  
  77.     }  
  78.   
  79.     public int search(int array[],int key) {    
  80.        return searchObj.binarySearch(array,key); //调用适配者类BinarySearch的查找方法  
  81.     }  
  82. }  

       为了让系统具备良好的灵活性和可扩展性,我们引入了工具类XMLUtil和配置文件,其中,XMLUtil类的代码如下所示:

  1. import javax.xml.parsers.*;  
  2. import org.w3c.dom.*;  
  3. import org.xml.sax.SAXException;  
  4. import java.io.*;  
  5. class XMLUtil {  
  6. //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象  
  7.     public static Object getBean() {  
  8.         try {  
  9.             //创建文档对象  
  10.             DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();  
  11.             DocumentBuilder builder = dFactory.newDocumentBuilder();  
  12.             Document doc;                             
  13.             doc = builder.parse(new File("config.xml"));   
  14.           
  15.             //获取包含类名的文本节点  
  16.             NodeList nl = doc.getElementsByTagName("className");  
  17.             Node classNode=nl.item(0).getFirstChild();  
  18.             String cName=classNode.getNodeValue();  
  19.               
  20.             //通过类名生成实例对象并将其返回  
  21.             Class c=Class.forName(cName);  
  22.             Object obj=c.newInstance();  
  23.             return obj;  
  24.         }     
  25.         catch(Exception e) {  
  26.             e.printStackTrace();  
  27.             return null;  
  28.         }  
  29.     }  
  30. }  

       配置文件config.xml中存储了适配器类的类名,代码如下所示:

  1. <?xml version="1.0"?>  
  2. <config>  
  3.     <className>OperationAdapter</className>  
  4. </config>  

       编写如下客户端测试代码:

  1. class Client {  
  2.     public static void main(String args[]) {  
  3.         ScoreOperation operation;  //针对抽象目标接口编程  
  4.         operation = (ScoreOperation)XMLUtil.getBean(); //读取配置文件,反射生成对象  
  5.         int scores[] = {84,76,50,69,90,91,88,96}; //定义成绩数组  
  6.         int result[];  
  7.         int score;  
  8.           
  9.         System.out.println("成绩排序结果:");  
  10.         result = operation.sort(scores);  
  11.   
  12.         //遍历输出成绩  
  13.         for(int i : scores) {  
  14.             System.out.print(i + ",");  
  15.         }  
  16.         System.out.println();  
  17.           
  18.         System.out.println("查找成绩90:");  
  19.         score = operation.search(result,90);  
  20.         if (score != -1) {  
  21.             System.out.println("找到成绩90。");  
  22.         }  
  23.         else {  
  24.             System.out.println("没有找到成绩90。");  
  25.         }  
  26.           
  27.         System.out.println("查找成绩92:");  
  28.         score = operation.search(result,92);  
  29.         if (score != -1) {  
  30.             System.out.println("找到成绩92。");  
  31.         }  
  32.         else {  
  33.             System.out.println("没有找到成绩92。");  
  34.         }  
  35.     }  
  36. }  

        编译并运行程序,输出结果如下:

成绩排序结果:

50,69,76,84,88,90,91,96,

查找成绩90

找到成绩90

查找成绩92

没有找到成绩92

       在本实例中使用了对象适配器模式,同时引入了配置文件,将适配器类的类名存储在配置文件中。如果需要使用其他排序算法类和查找算法类,可以增加一个新的适配器类,使用新的适配器来适配新的算法,原有代码无须修改。通过引入配置文件和反射机制,可以在不修改客户端代码的情况下使用新的适配器,无须修改源代码,符合“开闭原则”。

【作者:刘伟  http://blog.csdn.net/lovelion

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:170358次
    • 积分:2707
    • 等级:
    • 排名:第13974名
    • 原创:72篇
    • 转载:132篇
    • 译文:0篇
    • 评论:32条
    最新评论