最近在學習《Objective-C程式設計之道:iOS設計模式解析》,本文是對介面卡模式的一個分析和例子實現。
例子地址:Bryanthelol/iOS_DesignPattern
標籤:介面適配
一、介面卡模式是什麼
用於連線兩種不同種類的物件,使其毫無問題地協同工作
使得原本由於介面不相容而不能一起工作的那些類可以在一起工作。
介面卡模式主要應用於“希望複用一些現存的類,但是介面又與複用環境要求不一致的情況”,在遺留程式碼複用、類庫遷移等方面非常有用。
二、如何實現介面卡模式
兩種方式實現:
- 類介面卡
- 物件介面卡
類介面卡的實現
首先,我們來了解一下OC的一些特性:
Objective-C有協議,作為純粹抽象的一種形式
在Objective-C中,類可以實現協議,同時又繼承超類
因此,達到了多重繼承的效果
然後,可以根據這些語言特性來實現介面卡效果:
定義一套現在客戶端將要使用的協議
再用一個介面卡類實現這個協議
介面卡類繼承自被適配者(也就是那個與現有客戶端不相容的類)
關係圖如下:
Adapter繼承了Target協議的介面method方法,然後過載了method方法。在method方法中,Adapter繼承了Adaptee,但沒有過載specificMethod方法,而是直接呼叫超類specificMethod方法,在Adapter自己的環境下執行。
物件介面卡的實現
物件介面卡不繼承被介面卡,即Adapter不繼承Adaptee。而是用物件組合:Adapter持有一個Adaptee的例項引用。
關係圖如下:
和類介面卡的區別是:
- Adapter和Adaptee之間的關係從“繼承”變成了“包含”
- 這種關係下,Adapter需要保持一個對Adaptee的例項引用
在method方法中,Adapter通過adaptee例項,間接呼叫specificMethod方法,在Adapter自己的環境下執行。
類介面卡和物件介面卡的區別對比
-
類介面卡:
- 只針對單一的具體的Adaptee類,把Adaptee適配到Target
- 易於過載Adaptee的行為,因為是通過直接的子類化進行的適配
- 只有一個Adapter物件,無需額外的指標間接訪問Adaptee
-
物件介面卡:
- 可以適配多個Adaptee及其子類
- 難以過載Adaptee的行為,需要藉助於子類的物件而不是Adaptee本身
- 需要額外的指標以間接訪問Adaptee並適配其行為
三、用我自己的樣例程式碼講解
在我現在的專案裡,正好有一個例子。
情況是這樣,如圖:
點選了“新增圖片”按鈕後,會彈出下面的“拍照上傳”“從相簿選擇”選項,暫且稱作“彈出框”吧。
現在的問題是,“從相簿選擇”出現的選擇圖片介面,圖片只能被單選:
就像上面兩張圖展示的一樣,選擇一張照片後,就只能點確定了。其實就是使用了iOS自帶的原生相簿,功能不滿足需求。
現在的需求則是:能多選圖片,並且帶有排序,也能單獨編輯一張圖片。就和微信發朋友圈時上傳、編輯圖片一樣。
之後尋找了一個開源的圖片編輯庫IJSPhotoSDK,很好用很強大很好用。
現在的問題是,要把這個庫放進專案裡,但原則是儘量不改變呼叫者(就是上圖,點選“上傳圖片”按鈕的那個檢視類)的程式碼。
這時候介面卡模式就發揮了作用。
介面卡CameraCall類
這個“彈出框”就放在CameraCall這個類,而CameraCall就是我們的主角——介面卡。
回顧一下介面卡的關係類圖(這裡使用物件介面卡實現,因為需要適配多個Adaptee):
CameraCall介面卡符合了這兩個條件:
- 它有一個CameraCallDelegate協議,供呼叫者簽署然後實現
- 它持有IJSPhotoSDK圖片編輯庫的例項
因此,IJSPhotoSDK圖片編輯庫的例項只需要呼叫自己的方法,返回圖片資料,然後CameraCall介面卡呼叫協議例項的方法,把資料返回給呼叫者“上傳圖片”按鈕的那個檢視類就可以了。
在檢視類裡實現CameraCallDelegate協議裡的方法:
檢視類不用關心是哪個圖片編輯庫的什麼方法返回的資料,只關心協議方法返回的資料即可。
如果這時候,我們想換一個圖片編輯庫,就可以不改動呼叫者類的程式碼,只在CameraCall介面卡裡換成引入另一個影象編輯器,例項化這個編輯器,然後開始獲取資料的操作就可以了。
可以看到,介面卡模式本質上是把我們想要達成的這個“目的”抽象出來,放入這個叫介面卡的物件中。這個物件進行一系列操作,使得呼叫者只需實現這個介面卡物件即可,無需關心被適配者,就和現實中使用電源介面卡一樣。
最後我們的引入的圖片多選編輯功能就完成了: