設計模式的藝術 結構型模式之介面卡模式
不懂使用為學過,說出用途,繪製結構為了解,不會靈活使用基本等於沒學。
前言
有的筆記本工作電壓是20V,而中國家庭用電的電壓是220V,如何讓20V的筆記本在220V的電壓下工作,答案就是進入一個電源介面卡,這樣才能相容,在軟體開發中也有這種不相容的情況,這時候也可以像電源介面卡的方法一樣來使用一個扮演著介面卡角色的類來協調這些不相容的結構,這就是介面卡模式
什麼是介面卡模式 Adapter Pattern
將一個介面轉換成客戶所希望的另一個介面,使介面不相容的那些類也可以一起工作,其有個別名叫做包裝類,介面卡模式既可以作為類結構性模式,也可以作為物件結構性模式
(初學者可以參考SSM框架中的service層作為參考,介面卡模式遮蔽了底層程式碼的實現,service層也一樣)
注:介面卡模式中定義的介面是廣義上的介面,可以表示一個方法或者一個方法對的集合
介面卡模式的優點
(1)、將目標類和適配者類解耦,通過引入一個介面卡來重用現有的適配者類,無須修改原有結構,只需增加一個介面卡
(2)、增加了類的透明性和複用性,將具體的業務實現過程封裝在適配類中,對於客戶端而言是透明的,而且提高了適配類的複用性,同一個適配類可以在不同的系統中複用。
(3)、靈活性和擴充套件性都非常的好,通過使用配置檔案,可以很方便的切換介面卡,也可以在不修改原有程式碼的基礎上增加新的介面卡類,完全符合開閉原則。
(4)、對於物件介面卡而言,可以用一個物件介面卡將不同的適配者適配到同一個目標
介面卡模式的缺點
(1)、由於JAVA,C#語言的限制,不支援多重繼承的語言,一次最多隻能適配一個適配者類,不能同時適配多個適配者。
(2)、適配者不能是最終類,如Java中的final類,C#中的sealed類。
(3)、在Java C#這些語言中,類介面卡模式中的目標抽象類只能為介面,不能為類,其使用有一定的侷限性。
介面卡模式適用的場景
(1)、系統需要使用一些現有的類,而這些類的介面(例如方法名)不符合系統的需要,甚至沒有這些類的原始碼
(2)、想建立一些可以重複工作的類,用於與一些彼此之間沒有太大關聯的類,包括一些可能在將來引進的類一起工作
(3)、介面卡模式多用於在程式設計之後或者新增功能的時候,是一種補救的結構性模式
介面卡模式的具體實現(物件介面卡模式)
目錄結構(使用的開發工具是IDEA)
介面卡介面以及實現子類
package com.company;
public interface ScoreOperation {
public int[] sort(int array[]); //成績排序
public int search(int array[],int key); //成績查詢
}
package com.company;
public class OperatonAdapter implements ScoreOperation { //操作介面卡:介面卡
//定義介面卡物件QuickSort物件
private QuickSort quickSort;
//定義介面卡物件BinarySearch物件
private BinarySearch binarySearch;
public OperatonAdapter(){
quickSort=new QuickSort();
binarySearch=new BinarySearch();
}
@Override
public int[] sort(int[] array) {
//呼叫適配者類QuickSort的排序方法
return quickSort.quickSort(array);
}
@Override
public int search(int[] array, int key) {
//呼叫適配者類binarySearch的查詢方法
return binarySearch.binarySearch(array,key);
}
}
適配者類
public class QuickSort {
public int[] quickSort(int array[]){
sort(array,0,array.length-1);
return array;
}
public void sort(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);
}
}
}
public void swap(int[]a,int i,int j){
int t=a[i];
a[i]=a[j];
a[j]=t;
}
}
public 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; //找到元素返回一
}
}
return -1; //未找到返回-1;
}
}
輔助工具類
package com.company;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
public class XMLUtil {
//該類從配置檔案中提取一個具體類的類名,並返回一個例項物件
public static Object getBean(){
try {
//建立文件物件
DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder=documentBuilderFactory.newDocumentBuilder();
Document document=documentBuilder.parse(
new File(XMLUtil.class.getClassLoader().getResource("").getPath()+"config.xml"));
//獲取包含類名的文字節點
NodeList nodeList=document.getElementsByTagName("className");
Node node=nodeList.item(0).getFirstChild();
String name=node.getNodeValue();
//通過類名生成例項物件並將其返回
/*System.out.println(name);*/
Class c=Class.forName(name);
Object obj=c.newInstance();
return obj;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
配置檔案
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<className>com.company.OperatonAdapter</className>
</config>
客戶端測試類
package com.company;
public class Client {
public static void main(String[] args) {
ScoreOperation operation; //針對抽象目標介面程式設計
operation=(ScoreOperation) XMLUtil.getBean(); //讀取配置檔案,反射生成物件
int sroces[]={45,56,6,7,45,6}; //定義成績陣列
int result[];
int score;
System.out.println("成績排序結果:");
result=operation.sort(sroces);
//遍歷輸出成績
for (int i:result){
System.out.println(i);
}
System.out.println();
System.out.println("查詢成績56");
score=operation.search(sroces,56);
if(score!=-1){
System.out.println("找到成績56");
}else{
System.out.println("沒有找到成績56");
}
System.out.println("查詢成績77");
score=operation.search(sroces,77);
if(score!=-1){
System.out.println("找到成績77");
}else{
System.out.println("沒有找到成績77");
}
}
}
轉載請註明出處,掌聲送給社會人