前言
本文csdn地址:http://blog.csdn.net/game3108/article/details/51174787
本文主要以代碼形式實現(xiàn)每一種設計模式核芽,算是自己的一種復習和實踐。相應的代碼酵熙,也會放到github上轧简。
本文的類圖均來自于《Objective-C編程之道 iOS設計模式解析》。
本篇主要講:
- 適配器
- 橋接
- 外觀
6.適配器
概念:將一個類的接口轉(zhuǎn)換成客戶希望的另一個接口匾二。適配器模式使得原本由于接口不兼容而不能在一起工作的那些類可以一起工作哮独。
適配器主要有兩種實現(xiàn)方式:
- 類適配器
通過繼承來適配兩個接口。 - 對象適配器
組合一個適配器對象的引用察藐。
類圖:
何時使用:
- 已有類的接口與需求不匹配皮璧。
- 想要一個可復用的類,該類能夠同可能帶有不兼容接口的其他類協(xié)作分飞。
- 需要適配一個類的幾個不同自雷悴务,可是讓每一個子類去子類化一個類適配器又不現(xiàn)實,那么可以使用對象適配器(也叫委托)來適配其父類的接口譬猫。
類適配器的例子:
EATarget對象
#import <Foundation/Foundation.h>
@protocol EATarget <NSObject>
- (void) request;
@end
EAAdaptee對象:
#import <Foundation/Foundation.h>
@interface EAAdaptee : NSObject
- (void) specificRequest;
@end
#import "EAAdaptee.h"
@implementation EAAdaptee
- (void) specificRequest{
}
@end
EAAdapter對象:
#import "EAAdaptee.h"
#import "EATarget.h"
@interface EAAdapter : EAAdaptee<EATarget>
@end
#import "EAAdapter.h"
@implementation EAAdapter
- (void) request{
[super specificRequest];
//to do something
//xxxxxx
}
@end
對象適配器的例子:
delegate(委托)就是一個典型的對象適配器的用法讯檐。
UITableView
,通過delegate回調(diào)didSelectRowAtIndexPath
操作其他對象染服。其中UITableView
為client别洪,UITableViewDelegate
為target
OASelectObject Adaptee:
#import <Foundation/Foundation.h>
@interface OASelectObject : NSObject
- (void) didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
@end
#import "OASelectObject.h"
@implementation OASelectObject
- (void) didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
@end
OAUIViewController adapter對象
#import <UIKit/UIKit.h>
@interface OAUIViewController : UIViewController
@end
#import "OAUIViewController.h"
#import "OASelectObject.h"
@interface OAUIViewController ()<UITableViewDelegate,UITableViewDataSource>{
OASelectObject *_selectObject;
}
@end
@implementation OAUIViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
_selectObject = [[OASelectObject alloc]init];
UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 100, 100)];
tableView.backgroundColor = [UIColor blackColor];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellIdentifier = @"cell_identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if ( !cell ){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.backgroundColor = [UIColor grayColor];
}
return cell;
}
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[_selectObject didSelectRowAtIndexPath:indexPath];
}
@end
7.橋接
概念:將抽象部分與它的實現(xiàn)部分分離,使它們都可以獨立地變化柳刮。
類圖:
何時使用:
- 不想在抽象與其實現(xiàn)之間形成固定的綁定關系(這樣就能在運行時切換實現(xiàn))挖垛。
- 抽象及其實現(xiàn)都應可以通過子類化獨立進行擴展痒钝。
- 對抽象的實現(xiàn)進行修改不應影響客戶端代碼。
- 如果每個實現(xiàn)需要額外的子類以細化抽象痢毒,則說明有必要把它們分為兩個部分送矩。
- 想在帶有不同抽象接口的多個對象之間共享一個實現(xiàn)。
代碼場景:
電視遙控器會根據(jù)不同電視機改變它的實現(xiàn)哪替,而且遙控器本身也會改變益愈。所以抽象出電視和遙控器兩個抽象類出來。
電視類:
#import <Foundation/Foundation.h>
@interface TV : NSObject
- (void)on;
- (void)off;
- (void)tuneChannel:(NSInteger)channel;
@end
#import "TV.h"
@interface TV(){
NSInteger _nowChannel;
BOOL _onShow;
}
@end
@implementation TV
- (void)on{
_onShow = NO;
}
- (void)off{
_onShow = YES;
}
- (void)tuneChannel:(NSInteger)channel{
_nowChannel = channel;
}
@end
電視子類:
#import "TV.h"
@interface RCA : TV
@end
#import "RCA.h"
@implementation RCA
- (void)tuneChannel:(NSInteger)channel{
NSLog(@"RCA tunechannel");
[super tuneChannel:channel];
}
@end
#import "TV.h"
@interface Sony : TV
@end
#import "Sony.h"
@implementation Sony
- (void)tuneChannel:(NSInteger)channel{
NSLog(@"Sony tunechannel");
[super tuneChannel:channel];
}
@end
遙控類:
#import <Foundation/Foundation.h>
#import "TV.h"
@interface RemoveControl : NSObject
@property (nonatomic, strong) TV *implementor;
- (void) on;
- (void) off;
- (void) setChannel:(NSInteger)channel;
@end
#import "RemoveControl.h"
@implementation RemoveControl
- (void) on{
[_implementor on];
}
- (void) off{
[_implementor off];
}
- (void) setChannel:(NSInteger)channel{
[_implementor tuneChannel:channel];
}
@end
遙控子類:
#import "RemoveControl.h"
@interface ConcreteRemote : RemoveControl
- (void) setStation:(NSInteger)station;
- (void) nextChannel;
- (void) previousChannel;
@end
#import "ConcreteRemote.h"
@interface ConcreteRemote(){
NSInteger _currentStation;
}
@end
@implementation ConcreteRemote
- (void) setStation:(NSInteger)station{
_currentStation = station;
[super setChannel:station];
}
- (void) nextChannel{
[super setChannel:_currentStation + 1];
}
- (void) previousChannel{
[super setChannel:_currentStation - 1];
}
@end
8.外觀
概念:為系統(tǒng)中的一組接口提供一個統(tǒng)一的接口夷家。外觀定義一個高層接口,讓子系統(tǒng)更易于使用敏释。
結(jié)構(gòu)圖:
何時使用:
- 子系統(tǒng)正逐漸變得復雜库快。應用模式的過程中演化出許多類≡客纾可以使用外觀為這些子系統(tǒng)類提供一個較簡單的接口义屏。
- 可以使用外觀對子系統(tǒng)進行分層。每個子系統(tǒng)級別有一個外觀作為入口點蜂大。讓它們通過其外觀進行通信闽铐,可以簡化他們的依賴關系。
代碼場景:
家庭影院看電影的時候奶浦,可能要先放下屏幕兄墅,關燈,然后播放dvd等澳叉。使用外觀可以用一個家庭影院外觀類進行統(tǒng)一管理隙咸。
家庭外觀類:
#import <Foundation/Foundation.h>
#import "DvdPlayer.h"
#import "CdPlayer.h"
#import "Screen.h"
#import "TheaterLights.h"
@interface HomeTheaterFacade : NSObject
@property (nonatomic, strong) DvdPlayer *dvd;
@property (nonatomic, strong) CdPlayer *cd;
@property (nonatomic, strong) Screen *screen;
@property (nonatomic, strong) TheaterLights *lights;
- (void) watchMovie:(NSString*) movie;
- (void) endMovie;
@end
#import "HomeTheaterFacade.h"
@implementation HomeTheaterFacade
- (void) watchMovie:(NSString*) movie{
NSLog(@"get ready to watch a movie");
[_lights off];
[_screen down];
[_dvd on];
[_dvd play:movie];
}
- (void) endMovie{
NSLog(@"shutting movie theater down");
[_lights on];
[_screen up];
[_dvd stop];
[_dvd eject];
[_dvd off];
}
@end
總結(jié):
1.適配器,橋接成洗,外觀的使用時機五督?
- 適配器:用于設計完成之后,主要適用于解決兩個已有接口的匹配瓶殃,而接口本身是一個黑匣子充包,你無法去修改接口的實現(xiàn)。
- 橋接模式:用于設計的初期遥椿,參與接口的類是穩(wěn)定的基矮,用戶可以修改擴展和修改接口的類,但不能改變接口修壕,通過接口繼承實現(xiàn)或者類繼承實現(xiàn)功能擴展愈捅。
- 外觀模式:用于設計的初期,為一組子接口提供統(tǒng)一接口慈鸠。相對于適配器的小粒度功能繼承蓝谨,更像一個大粒度的適配器灌具,當封裝系統(tǒng)演化的時候,需要新的外觀對象譬巫,而這個對象起到了適配器的作用咖楣。
參考資料
1.《Objective-C編程之道 iOS設計模式解析》
2.《Head First設計模式》
3.設計模式學習筆記十四:適配器模式、橋接模式與外觀模式