原文出處: Lastdays(@Lastday_s)
很好奇,什麼是適配器,大家有沒有聽說過電源適配器,其實原理都是一樣的,就是說我們的iPhone手機,在中國,可以用iPhone充電器給手機充電,都知道,中國的電壓是220V,對吧,我們的iPhone額定輸入電壓是5V,其實這就是我們適配器的功勞,而且,我們的充電器在中國能用,當然如果我們去了美國,沒過不是220V,難道我們的手機就不能充電了嗎?當然肯定不會,總結來說:在計算機編程中,適配器模式(有時候也稱包裝樣式或者包裝)將一個類的接口適配成用戶所期待的。一個適配允許通常因爲接口不兼容而不能在一起工作的類工作在一起,做法是將類自己的接口包裹在一個已存在的類中。
爲何使用適配器?
直接賦值的缺點
最簡單明瞭就是直接寫一個示例來說名
製作一張卡片:
對卡片的數據直接賦值:
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #import "ViewController.h" #import "BusinessCard.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. BusinessCard *card = [[BusinessCard alloc] initWithFrame:BUSINESS_FRAME]; card.name = @"姓名"; card.color = [UIColor blueColor]; card.phoneNumber = @"電話"; card.center = self.view.center; [self.view addSubview:card]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end |
運行結果:
非常簡單的一個示例,這基本上就是我們以前經常使用的一種方法直接賦值,這種的缺點,其實很簡單,就是耦合性太強了,簡簡單單的移除更改,可能就會造成很多地方進行更改。現在看起來很簡單就更改,但是如果我們的數據很多很多呢?
因此我們現在簡單的來改進一下,設計一個model。並且在BusinessCard添加如下代碼:
Objective-C
1 2 3 4 5 6 7 8 9 10 | /** * 初始化數據 * * @param model BusinessCard */ -(void)loadDataWithModel:(Model *)model{ self.name = model.name; self.phoneNumber = model.phoneNumber; self.line = model.lineColor; } |
ViewController:
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib Model *model = [[Model alloc] initWithName:@"lastdays" phoneNumber:@"158******1111" lineColor:[UIColor blueColor]]; BusinessCard *card = [[BusinessCard alloc] initWithFrame:BUSINESS_FRAME]; card.center = self.view.center; [card loadDataWithModel:model]; [self.view addSubview:card]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end |
這樣就降低了一些耦合性,這就是以對象形式賦值。
但是我們現在來闡述一個很致命的問題,那就是如果我們來了一個新的Model數據類型,其中的UIcolor是二進制形的。跟我們原來處理的數據類型不符合?這個時候怎麼辦?
其實解決方案很簡單,這也就是上面提到過的,電源適配器原理。
使用適配器模型
電源有輸入和輸出,當然我們先來構建適配器
CardAdapterProtocol:
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 | #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @protocol CardAdapterProtocol <NSObject> - (NSString *)name; - (UIColor *)lineColor; - (NSString *)phoneNumber; @end |
CardAdapter:
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #import <Foundation/Foundation.h> #import "CardAdapterProtocol.h" #import <UIKit/UIKit.h> @interface CardAdapter : NSObject<CardAdapterProtocol> /** * 建立輸入關係 */ @property(nonatomic,weak) id data; /** * 與輸入對象建立聯繫 * * @param data 輸入的對象 * * @return 當前實例對象 */ - (instancetype)initWithModel:(id)data; @end ``` ``` bash #import "CardAdapter.h" @implementation CardAdapter - (NSString *)name{ return nil; } - (UIColor *)lineColor{ return nil; } - (NSString *)phoneNumber{ return nil; } @end |
這裏我們構建了CardAdapterProtocol協議,以及抽象類CardAdapter,接下來就是創建ModelCardAdapter,這就是針對Model構建的適配器,然後覆蓋內部方法進行重寫。
這裏需要做一下說明CardAdapter中通過initWithModel建立與Model的輸入關係,就是我們在國內用充電器給手機充電,CardAdapter與Model的關係就是充電器跟220V電壓的關係。
接下來就該建立充電器跟手機的關係了,這裏面相當於構建CardAdapter和View的關係。
BusinessCard
Objective-C
1 2 3 4 5 6 7 8 9 10 | /** * 初始化卡片數據 * * @param model BusinessCard */ -(void)loadDataWithModel:(id<CardAdapterProtocol>)data{ self.name = [data name]; self.phoneNumber = [data phoneNumber]; self.line = [data lineColor]; } |
這樣,我們基本上就完成了構建,測試:
ViewController:
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #import "ViewController.h" #import "BusinessCard.h" #import "Model.h" #import "ModelCardAdapter.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. Model *model = [[Model alloc] initWithName:@"lastdays" phoneNumber:@"158******1111" lineColor:[UIColor blueColor]]; //建立充電器跟電源關係 CardAdapter *cardAdapter = [[ModelCardAdapter alloc] initWithModel:model]; BusinessCard *card = [[BusinessCard alloc] initWithFrame:BUSINESS_FRAME]; card.center = self.view.center; //建立手機跟充電器關係 [card loadDataWithModel:cardAdapter]; [self.view addSubview:card]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end |
測試結果:
以上我們使用的就是類適配器,當然還有一種叫做對象適配器,就是說無論我們是220V,還是100V,用這一個充電器都能給手機充電。這種如何實現?簡單的說就是我們可以構建一個Adapter繼承CardAdapter,簡單的舉個例子
Adapter
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | - (NSString *)name { NSString *name = nil; if ([self.data isMemberOfClass:[Model class]]) { Model *model = self.data; name = model.name; } else if ([self.data isMemberOfClass:[NewCardModel class]]) { NewCardModel *model = self.data; name = model.name; } return name; } |
根絕對象類型進行判斷返回哪種處理結果。這種其實並不推薦,因爲什麼?因爲現在的數據模型比較少,如果有10個,20個數據模型,那這個類到最好會非常的臃腫,並不方便我們維護。
總結
優點
優點顯而易見,就是讓適配器可以讓我們的View更加強大,可以適配不同的數據,降低我們的耦合性
缺點
其實在代碼中就可以看出來,一個簡單賦值的東西,用了這麼多東西,比較麻煩,有的時候是很繁瑣的。但是呢?話又說回來,我們如果做了一個很牛的控件,爲了提高它的通用性,加一個適配器會更好一些。 當我們的代碼能力增加。但是呢? 這同樣也是一個缺點,那就是代碼的可讀性不好。這點的權衡就靠自己來衡量,雖然麻煩一些,但是確實能夠提高擴展性。
QQ技術交流羣290551701
http://cxy.liuzhihengseo.com/524.html