不相容結構的協調——介面卡模式(二)

Liuwei-Sunny發表於2013-03-01

9.3 完整解決方案

      Sunny軟體公司開發人員決定使用介面卡模式來重用演算法庫中的演算法,其基本結構如圖9-4所示:

9-4  演算法庫重用結構圖

       在圖9-4中,ScoreOperation介面充當抽象目標,QuickSortBinarySearch類充當適配者,OperationAdapter充當介面卡。完整程式碼如下所示:

//抽象成績操作類:目標介面
interface ScoreOperation {
	public int[] sort(int array[]); //成績排序
	public int search(int array[],int key); //成績查詢
}

//快速排序類:適配者
class QuickSort {
	public int[] quickSort(int array[]) {
		sort(array,0,array.length-1);
		return array;
	}

	public void sort(int array[],int p, int r) {
		int q=0;
		if(p<r) {
			q=partition(array,p,r);
			sort(array,p,q-1);
            sort(array,q+1,r);
		}
	}

	public int partition(int[] a, int p, int r) {
		int x=a[r];
		int j=p-1;
		for (int i=p;i<=r-1;i++) {
			if (a[i]<=x) {
				j++;
				swap(a,j,i);
			}
		}
		swap(a,j+1,r);
		return j+1;	
	}

	public void swap(int[] a, int i, int j) {   
        int t = a[i];   
        a[i] = a[j];   
        a[j] = t;   
	}
}

//二分查詢類:適配者
class BinarySearch {
	public int binarySearch(int array[],int key) {
		int low = 0;
		int high = array.length -1;
		while(low <= high) {
			int mid = (low + high) / 2;
			int midVal = array[mid];
			if(midVal < key) {  
low = mid +1;  
}
			else if (midVal > key) {  
high = mid -1;  
}
			else {  
return 1; //找到元素返回1  
}
		}
		return -1;  //未找到元素返回-1
	}
}

//操作介面卡:介面卡
class OperationAdapter implements ScoreOperation {
	private QuickSort sortObj; //定義適配者QuickSort物件
	private BinarySearch searchObj; //定義適配者BinarySearch物件

	public OperationAdapter() {
		sortObj = new QuickSort();
		searchObj = new BinarySearch();
	}

	public int[] sort(int array[]) {  
return sortObj.quickSort(array); //呼叫適配者類QuickSort的排序方法
}

	public int search(int array[],int key) {  
return searchObj.binarySearch(array,key); //呼叫適配者類BinarySearch的查詢方法
}
}

       為了讓系統具備良好的靈活性和可擴充套件性,我們引入了工具類XMLUtil和配置檔案,其中,XMLUtil類的程式碼如下所示:

import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
class XMLUtil {
//該方法用於從XML配置檔案中提取具體類類名,並返回一個例項物件
	public static Object getBean() {
		try {
			//建立文件物件
			DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = dFactory.newDocumentBuilder();
			Document doc;							
			doc = builder.parse(new File("config.xml")); 
		
			//獲取包含類名的文字節點
			NodeList nl = doc.getElementsByTagName("className");
            Node classNode=nl.item(0).getFirstChild();
            String cName=classNode.getNodeValue();
            
            //通過類名生成例項物件並將其返回
            Class c=Class.forName(cName);
	  	    Object obj=c.newInstance();
            return obj;
        }   
        catch(Exception e) {
           	e.printStackTrace();
           	return null;
       	}
	}
}

       配置檔案config.xml中儲存了介面卡類的類名,程式碼如下所示:

<?xml version="1.0"?>
<config>
	<className>OperationAdapter</className>
</config>

       編寫如下客戶端測試程式碼:

class Client {
	public static void main(String args[]) {
		ScoreOperation operation;  //針對抽象目標介面程式設計
		operation = (ScoreOperation)XMLUtil.getBean(); //讀取配置檔案,反射生成物件
		int scores[] = {84,76,50,69,90,91,88,96}; //定義成績陣列
		int result[];
		int score;
		
		System.out.println("成績排序結果:");
		result = operation.sort(scores);

        //遍歷輸出成績
		for(int i : scores) {
			System.out.print(i + ",");
		}
		System.out.println();
		
		System.out.println("查詢成績90:");
		score = operation.search(result,90);
		if (score != -1) {
			System.out.println("找到成績90。");
		}
		else {
			System.out.println("沒有找到成績90。");
		}
		
		System.out.println("查詢成績92:");
		score = operation.search(result,92);
		if (score != -1) {
			System.out.println("找到成績92。");
		}
		else {
			System.out.println("沒有找到成績92。");
		}
	}
}

        編譯並執行程式,輸出結果如下:

成績排序結果:

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

查詢成績90

找到成績90

查詢成績92

沒有找到成績92

       在本例項中使用了物件介面卡模式,同時引入了配置檔案,將介面卡類的類名儲存在配置檔案中。如果需要使用其他排序演算法類和查詢演算法類,可以增加一個新的介面卡類,使用新的介面卡來適配新的演算法,原有程式碼無須修改。通過引入配置檔案和反射機制,可以在不修改客戶端程式碼的情況下使用新的介面卡,無須修改原始碼,符合“開閉原則”。

【作者:劉偉  http://blog.csdn.net/lovelion

相關文章