iOS 設(shè)計(jì)模式之七(適配器模式)

一圈纺、概念

1链沼、適配器模式的動機(jī)

? 目前手機(jī)的充電電壓是5伏到幾十伏不等默赂,但是我國標(biāo)準(zhǔn)居民用電電壓是220v,那么如何對手機(jī)進(jìn)行充電呢括勺?答案大家都知道缆八,使用充電器,也叫電源適配器疾捍。在軟件開發(fā)中奈辰,有時也存在類似這種不兼容的情況,我們也可以像引入一個電源適配器一樣引入一個稱之為適配器的角色來協(xié)調(diào)這些存在不兼容的結(jié)構(gòu)乱豆,這種設(shè)計(jì)方案即為適配器模式奖恰。

2、適配器模式的定義

? 適配器模式(Adapter Pattern):將一個接口轉(zhuǎn)換成客戶希望的另一個接口宛裕,使接口不兼容的那些類可以一起工作瑟啃,其別名為包裝器(Wrapper)。適配器模式既可以作為類結(jié)構(gòu)型模式揩尸,也可以作為對象結(jié)構(gòu)型模式蛹屿。

? 根據(jù)適配器類與適配者類的關(guān)系不同,適配器模式可分為對象適配器和類適配器兩種疲酌。在對象適配器模式中蜡峰,適配器與適配者之間是關(guān)聯(lián)關(guān)系;在類適配器模式中朗恳,適配器與適配者之間是繼承(或?qū)崿F(xiàn))關(guān)系湿颅。

3、適配器的3個角色

1)Target(目標(biāo)抽象類):目標(biāo)抽象類定義客戶所需接口粥诫,可以是一個抽象類或接口油航,也可以是具體類。

2)Adapter(適配器類):適配器可以調(diào)用另一個接口怀浆,作為一個轉(zhuǎn)換器谊囚,對Adaptee和Target進(jìn)行適配怕享,適配器類是適配器模式的核心,在對象適配器中镰踏,它通過繼承Target并關(guān)聯(lián)一個Adaptee對象使二者產(chǎn)生聯(lián)系函筋。

3)Adaptee(適配者類):適配者即被適配的角色,它定義了一個已經(jīng)存在的接口奠伪,這個接口需要適配末荐,適配者類一般是一個具體類代嗤,包含了客戶希望使用的業(yè)務(wù)方法华畏。

4媳荒、對象適配器-結(jié)構(gòu)圖

? 對象適配器使用較廣,結(jié)構(gòu)圖如圖所示:

對象適配器模式
5滤否、類適配器-結(jié)構(gòu)圖

? 適配器類實(shí)現(xiàn)了抽象目標(biāo)類接口Target脸狸,并繼承了適配者類,在適配器類的request()方法中調(diào)用所繼承的適配者類的specificRequest()方法藐俺,實(shí)現(xiàn)了適配炊甲。大部分情況下我們使用的是對象適配器,類適配器較少使用紊搪。

類適配器模式

二蜜葱、對象適配器示例

1)先定義一個Electrical電器類,它有個charge()充電方法耀石,是目標(biāo)抽象類牵囤;

2)然后定義一個Television類,繼承自Electrical滞伟,是普通的電器揭鳞;

3)然后定義一個IphoneAdapter類蘋果電源適配器,繼承自Electrical類梆奈;

4)最后創(chuàng)建一個IphoneAdaptee類野崇,里面包含了具體的iPhone充電方法。

具體代碼如下:

Electrical類:

@interface Electrical: NSObject
- (void)charge;
@end

@implementation Electrical
- (void)charge {
    
}
@end

Television類:

@interface Television : Electrical
@end

@implementation Television
- (void)charge { //在子類實(shí)現(xiàn)方法
    NSLog(@"電視充電220v");
}
@end

IphoneAdapter類:

@interface IphoneAdapter : Electrical
- (instancetype)initWithAdaptee:(IphoneAdaptee *)adaptee; //初始化方法亩钟,引入Adaptee
@end

@interface IphoneAdapter ()
@property(nonatomic, strong) IphoneAdaptee *adaptee;
@end

@implementation IphoneAdapter
- (instancetype)initWithAdaptee:(IphoneAdaptee *)adaptee {
    self = [super init];
    if (self) {
        _adaptee = adaptee;
    }
    return self;
}

- (void)charge {
    [self.adaptee iphoneCharge]; //實(shí)現(xiàn)轉(zhuǎn)發(fā)調(diào)用效果
}
@end

IphoneAdaptee類:

@interface IphoneAdaptee : NSObject
- (void)iphoneCharge;
@end

@implementation IphoneAdaptee
- (void)iphoneCharge {
    NSLog(@"蘋果充電5v");
}
@end

運(yùn)行代碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Television *tv = [Television new];
    [tv charge];
    
    IphoneAdaptee *adaptee = [IphoneAdaptee new];
    IphoneAdapter *adapter = [[IphoneAdapter alloc] initWithAdaptee:adaptee];
    [adapter charge];
}

打印結(jié)果:

電視充電220v
蘋果充電5v

三乓梨、類適配器示例

1)和上面類似,先創(chuàng)建一個Electrical協(xié)議清酥,有一個charge()方法扶镀,表示目標(biāo)抽象類;

2)然后創(chuàng)建一個Television類焰轻,遵循Electrical協(xié)議臭觉;

3)然后創(chuàng)建一個IphoneAdaptee類,有iphoneCharge()方法,表示適配者蝠筑;

4)最后創(chuàng)建IphoneAdapter類狞膘,繼承自IphoneAdaptee類,并遵循Electrical協(xié)議什乙,表示適配器挽封。

具體代碼如下:

Electrical協(xié)議:

@protocol Electrical <NSObject>
- (void)charge;
@end

Television類:

@interface Television : NSObject<Electrical>
@end

@implementation Television
- (void)charge {
    NSLog(@"電視充電220v");
}
@end

IphoneAdaptee類:

@interface IphoneAdaptee : NSObject
- (void)iphoneCharge;
@end

@implementation IphoneAdaptee
- (void)iphoneCharge {
    NSLog(@"蘋果充電5v");
}
@end

IphoneAdapter類:

@interface IphoneAdapter : IphoneAdaptee<Electrical>
@end

@implementation IphoneAdapter
- (void)charge {
    [self iphoneCharge];
}
@end

運(yùn)行代碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Television *tv = [Television new];
    [tv charge];
    
    IphoneAdapter *adapter = [IphoneAdapter new];
    [adapter charge];
}

打印結(jié)果:

電視充電220v
蘋果充電5v

四、缺省適配器模式

? 缺省適配器模式是適配器模式的一種變體稳强,其應(yīng)用也較為廣泛场仲。

1和悦、缺省適配器模式的定義

? 缺省適配器模式(Default Adapter Pattern):當(dāng)不需要實(shí)現(xiàn)一個接口所提供的所有方法時退疫,可先設(shè)計(jì)一個抽象類實(shí)現(xiàn)該接口,并為接口中每個方法提供一個默認(rèn)實(shí)現(xiàn)(空方法)鸽素,那么該抽象類的子類可以選擇性地覆蓋父類的某些方法來實(shí)現(xiàn)需求褒繁,它適用于不想使用一個接口中的所有方法的情況,又稱為單接口適配器模式馍忽。

2棒坏、缺省適配器模式的3個角色

1)ServiceInterface(適配者接口):通常在該接口中聲明了大量的方法。

2)AbstractServiceClass(缺省適配器類):它是缺省適配器模式的核心類遭笋,使用空方法的形式實(shí)現(xiàn)了在ServiceInterface接口中聲明的方法坝冕,通常將它定義為抽象類。

3)ConcreteServiceClass(具體業(yè)務(wù)類):它是缺省適配器類的子類瓦呼,根據(jù)需要有選擇性地覆蓋在適配器類中定義的方法喂窟。

3、缺省適配器模式的結(jié)構(gòu)圖
缺省適配器模式
4央串、Demo示例

1)先創(chuàng)建一個AnimalProtocol協(xié)議磨澡,里面定義了幾個動物的方法,是ServiceInterface適配者接口质和;

2)然后創(chuàng)建一個抽象類Animal稳摄,遵循AnimalProtocol協(xié)議,并實(shí)現(xiàn)所有的方法-空方法饲宿,是AbstractServiceClass缺省適配器類厦酬;

3)最后創(chuàng)建一個Fish類,繼承自Animal類瘫想,并實(shí)現(xiàn)了fish的方法仗阅,是ConcreteServiceClass具體業(yè)務(wù)類。

具體代碼如下:

AnimalProtocol類:

@protocol AnimalProtocol <NSObject>
- (void)eat;
- (void)run;
- (void)swim;
@end

Animal類:

@interface Animal : NSObject <AnimalProtocol>
@end

@implementation Animal
- (void)eat {}
- (void)run {}
- (void)swim {}
@end

Fish類:

@interface Fish : Animal
@end

@implementation Fish
- (void)eat {
    NSLog(@"魚兒吃魚餌");
}

- (void)swim {
    NSLog(@"魚兒能游泳");
}
@end

運(yùn)行代碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Fish *fish = [Fish new];
    [fish eat];
    [fish swim];
}

打印結(jié)果:

魚兒吃魚餌
魚兒能游泳

五殿托、總結(jié)

? 適配器模式將現(xiàn)有接口轉(zhuǎn)化為客戶類所期望的接口霹菊,實(shí)現(xiàn)了對現(xiàn)有類的復(fù)用,它是一種使用頻率非常高的設(shè)計(jì)模式,在軟件開發(fā)中得以廣泛應(yīng)用旋廷。

1鸠按、優(yōu)點(diǎn)

? 對象適配器模式和類適配器模式都有的優(yōu)點(diǎn):

1、將目標(biāo)類和適配者類解耦饶碘,通過引入一個適配器類來重用現(xiàn)有的適配者類目尖,無須修改原有結(jié)構(gòu)。

2扎运、增加了類的透明性和復(fù)用性瑟曲,將具體的業(yè)務(wù)實(shí)現(xiàn)過程封裝在適配者類中,對于客戶端類而言是透明的豪治,而且提高了適配者的復(fù)用性洞拨,同一個適配者類可以在多個不同的系統(tǒng)中復(fù)用。

3负拟、靈活性和擴(kuò)展性好烦衣,通過使用配置文件,可以很方便地更換適配器掩浙,也可以在不修改原有代碼的基礎(chǔ)上增加新的適配器類花吟,完全符合“開閉原則”。

? 類適配器還有的優(yōu)點(diǎn):

? 由于適配器類是適配者類的子類厨姚,因此可以在適配器類中置換一些適配者的方法衅澈,使得適配器的靈活性更強(qiáng)。

? 對象適配器模式還有的優(yōu)點(diǎn):

1谬墙、一個對象適配器可以把多個不同的適配者適配到同一個目標(biāo)今布。

2、可以適配一個適配者的子類芭梯,由于適配器和適配者之間是關(guān)聯(lián)關(guān)系险耀,根據(jù)“里氏代換原則”,適配者的子類也可通過該適配器進(jìn)行適配玖喘。

2甩牺、缺點(diǎn)

? 類適配器缺點(diǎn):

1、對于Java累奈、C#等不支持多重類繼承的語言贬派,一次最多只能適配一個適配者類,不能同時適配多個適配者澎媒。

2搞乏、適配者類不能為最終類,如在Java中不能為final類戒努,C#中不能為sealed類请敦。

3、 在Java、C#等語言中侍筛,類適配器模式中的目標(biāo)抽象類只能為接口萤皂,不能為類,其使用有一定的局限性匣椰。

? 對象適配器缺點(diǎn):

? 與類適配器模式相比裆熙,要在適配器中置換適配者類的某些方法比較麻煩。如果一定要置換掉適配者類的一個或多個方法禽笑,可以先做一個適配者類的子類入录,將適配者類的方法置換掉,然后再把適配者類的子類當(dāng)做真正的適配者進(jìn)行適配佳镜,實(shí)現(xiàn)過程較為復(fù)雜僚稿。

3、適用場景

1邀杏、系統(tǒng)需要使用一些現(xiàn)有的類贫奠,而這些類的接口(如方法名)不符合系統(tǒng)的需要,甚至沒有這些類的源代碼望蜡。

2、想創(chuàng)建一個可以重復(fù)使用的類拷恨,用于與一些彼此之間沒有太大關(guān)聯(lián)的一些類脖律,包括一些可能在將來引進(jìn)的類一起工作。

4腕侄、APP應(yīng)用舉例

? Android的ListView就是通過adapter來實(shí)現(xiàn)所有的布局和事件操作的小泉。

Demo地址:iOS-Design-Patterns

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市冕杠,隨后出現(xiàn)的幾起案子微姊,更是在濱河造成了極大的恐慌,老刑警劉巖分预,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兢交,死亡現(xiàn)場離奇詭異,居然都是意外死亡笼痹,警方通過查閱死者的電腦和手機(jī)配喳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來凳干,“玉大人晴裹,你說我怎么就攤上這事【却停” “怎么了涧团?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我泌绣,道長喳瓣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任赞别,我火速辦了婚禮畏陕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘仿滔。我一直安慰自己惠毁,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布崎页。 她就那樣靜靜地躺著鞠绰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪飒焦。 梳的紋絲不亂的頭發(fā)上蜈膨,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機(jī)與錄音牺荠,去河邊找鬼翁巍。 笑死,一個胖子當(dāng)著我的面吹牛休雌,可吹牛的內(nèi)容都是我干的灶壶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼杈曲,長吁一口氣:“原來是場噩夢啊……” “哼驰凛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起担扑,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤恰响,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涌献,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胚宦,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年洁奈,在試婚紗的時候發(fā)現(xiàn)自己被綠了间唉。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡利术,死狀恐怖呈野,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情印叁,我是刑警寧澤被冒,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布军掂,位于F島的核電站,受9級特大地震影響昨悼,放射性物質(zhì)發(fā)生泄漏蝗锥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一率触、第九天 我趴在偏房一處隱蔽的房頂上張望终议。 院中可真熱鬧,春花似錦葱蝗、人聲如沸穴张。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽皂甘。三九已至,卻和暖如春悼凑,著一層夾襖步出監(jiān)牢的瞬間偿枕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工户辫, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留渐夸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓寸莫,卻偏偏與公主長得像捺萌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子膘茎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容