設計模式深入淺出(四)介面適配——介面卡
介面卡模式可以說是一個典型的介面適配模式。
一個現實中的例子
現在讓我設想這麼一個問題,如何讓別人寫好的已有的類介面,無縫的融合到我們自己的工程中?前提是,你無法獲取到別人的原始碼,也就是你不能夠修改別人的程式碼。
舉一個我們APP中的例子:
我們的APP是一款類似於雲盤檔案管理系統的軟體。它能夠接入GoogleDrive,OneDrive,Dropbox等第三方雲盤系統。
當然,接入第三方雲盤,自然使用的是第三方提供的SDK。
在我們的APP中,所用的雲盤檔案,均是抽象為NXFileBase型別的。而第三方SDK的檔案型別則各有不同,如GoogleDrive的檔案型別可能就是GTLDriveFile之類。
同時,不同雲盤SDK獲取檔案列表,下載檔案等操作的介面也不盡相同。
這就面臨一個問題:
介面的異構性導致了介面間的不匹配。
就像是我們那國內的充電器插頭到美國一樣,你根本沒法用,因為插頭規格標準是一樣的。
我們的做法是,為所有的雲盤SDK新增一層封裝,比如GoogleDriver,我們將GoogleDrive的SDK封裝在NXGoogleDrive中,而這層封裝符合協議NXServiceOperation。
程式碼如下:
@class NXFileBase;
@protocol NXServiceOperation <NSObject>
@required -(BOOL) getFiles:(NXFileBase*)folder;
@required -(BOOL) getAllFilesInFolder:(NXFileBase *) folder;
@required -(BOOL) cancelGetFiles:(NXFileBase*)folder;
@required -(BOOL) downloadFile:(NXFileBase*)file;
@required -(BOOL) cancelDownloadFile:(NXFileBase*)file;
@required -(BOOL) deleteFileItem:(NXFileBase*)file;
@required -(BOOL) addFolder:(NSString *)folderName toPath:(NXFileBase *)parentFolder;
...
@end
@interface NXGoogleDrive : NSObject<NXServiceOperation>
- (id) initWithUserId: (NSString *)userId repoModel:(NXRepositoryModel *)repoModel;
@end
// NXGoogleDrive內部實現會呼叫GoogleDrive 的SDK:
@implementation NXGoogleDrive
- (BOOL) getFiles:(NXFileBase *)folder {
if (!folder || ![folder isKindOfClass:[NXFolder class]]) {
return NO;
}
if([folder isRoot]) {
folder.fullPath = @"/";
folder.fullServicePath = kKeyGoogleDriveRoot;
}
// 呼叫GoogleSDK
GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
query.q = [NSString stringWithFormat:@"trashed = false and '%@' IN parents", folder.fullServicePath];
_driveService.shouldFetchNextPages = YES;
GTLServiceTicket *fileTicket = [_driveService executeQuery:query delegate:self didFinishSelector:@selector(getFilesFinishedwithTicket:fileList:error:)];
fileTicket.properties = [NSDictionary dictionaryWithObjectsAndKeys:folder, kKeyGetFiles, nil];
if (fileTicket) {
[_listFilesTickets setObject:fileTicket forKey:folder.fullServicePath];
}
return YES;
}
@end
同樣,對於OneDrive,DropBox我們也做了對應的封裝為:NXOneDrive,NXDropBox,它們同樣遵循NXServiceOperation協議。
這樣,UML圖為
在這裡,符合NXServiceOperation協議的NXGoogleDrive,NXOneDrive,NXDropBox相當於對第三方SDK做了一層適配,讓他們能夠無縫的整合與我們的APP中。
這就是介面卡模式的典型應用。
介面卡模式的定義為:
將一個類的介面轉換成客戶希望的另一個介面。Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以一起工作。《設計模式》
介面卡模式的實現由兩種方案:
介面卡模式的兩種實現
物件組合
實現同我們上面的例子,將被適配方Adaptee作為一個成員放在介面卡(Adapter)裡面。Client呼叫Adapter介面,而Adapter內部呼叫Adaptee相應介面做具體實現。
多重繼承
多重繼承就是讓Adapter繼承Target,使之能夠取得與Target相同的介面供Client呼叫,同時,繼承Adaptee,使Adapter的介面實現能夠呼叫Adaptee的方法,同時能夠重寫Adaptee方法,這是採用多重繼承與物件組合的方式實現介面卡模式最大的不同。
對於OC語言來說,不支援多繼承,我們可以用Adapter遵循Target協議,同時繼承Adaptee類來實現。