一绘证、概念
1、代理模式的動(dòng)機(jī)
? 隨著貿(mào)易的發(fā)展贿堰,網(wǎng)絡(luò)代購(gòu)成為一道亮麗的風(fēng)景線。顧客本地買不到需要的產(chǎn)品啡彬,便找代購(gòu)去外國(guó)把產(chǎn)品買回來(lái)羹与,也就是顧客只需要和代購(gòu)交流便可以買產(chǎn)品了。
? 在軟件開發(fā)中庶灿,也有一種設(shè)計(jì)模式可以提供與代購(gòu)類似的功能纵搁。由于某些原因,客戶端不想或不能直接訪問一個(gè)對(duì)象往踢,此時(shí)可以通過一個(gè)稱之為“代理”的第三者來(lái)實(shí)現(xiàn)間接訪問腾誉,該方案對(duì)應(yīng)的設(shè)計(jì)模式被稱為代理模式。
2峻呕、代理模式的定義
? 代理模式(Proxy Pattern):給某一個(gè)對(duì)象提供一個(gè)代理或占位符利职,并由代理對(duì)象來(lái)控制對(duì)原對(duì)象的訪問。
3瘦癌、代理模式的3個(gè)角色
1)Subject(抽象主題角色):它聲明了真實(shí)主題和代理主題的共同接口猪贪,這樣一來(lái)在任何使用真實(shí)主題的地方都可以使用代理主題,客戶端通常需要針對(duì)抽象主題角色進(jìn)行編程讯私。
2)Proxy(代理主題角色):它包含了對(duì)真實(shí)主題的引用哮伟,從而可以在任何時(shí)候操作真實(shí)主題對(duì)象;在代理主題角色中提供一個(gè)與真實(shí)主題角色相同的接口妄帘,以便在任何時(shí)候都可以替代真實(shí)主題。代理主題角色還可以控制對(duì)真實(shí)主題的使用池凄,負(fù)責(zé)在需要的時(shí)候創(chuàng)建和刪除真實(shí)主題對(duì)象抡驼,并對(duì)真實(shí)主題對(duì)象的使用加以約束。
3)RealSubject(真實(shí)主題角色):它定義了代理角色所代表的真實(shí)對(duì)象肿仑,在真實(shí)主題角色中實(shí)現(xiàn)了真實(shí)的業(yè)務(wù)操作致盟,客戶端可以通過代理主題角色間接調(diào)用真實(shí)主題角色中定義的操作碎税。
4、結(jié)構(gòu)圖
5馏锡、常用的代理模式分類
1)遠(yuǎn)程代理(Remote Proxy):為一個(gè)位于不同的地址空間的對(duì)象提供一個(gè)本地的代理對(duì)象雷蹂,這個(gè)不同的地址空間可以是在同一臺(tái)主機(jī)中,也可是在另一臺(tái)主機(jī)中杯道,遠(yuǎn)程代理又稱為大使(Ambassador)匪煌。
2)虛擬代理(Virtual Proxy):如果需要?jiǎng)?chuàng)建一個(gè)資源消耗較大的對(duì)象,先創(chuàng)建一個(gè)消耗相對(duì)較小的對(duì)象來(lái)表示党巾,真實(shí)對(duì)象只在需要時(shí)才會(huì)被真正創(chuàng)建萎庭。
3)保護(hù)代理(Protect Proxy):控制對(duì)一個(gè)對(duì)象的訪問,可以給不同的用戶提供不同級(jí)別的使用權(quán)限齿拂。
4)緩沖代理(Cache Proxy):為某一個(gè)目標(biāo)操作的結(jié)果提供臨時(shí)的存儲(chǔ)空間驳规,以便多個(gè)客戶端可以共享這些結(jié)果。
5)智能引用代理(Smart Reference Proxy):當(dāng)一個(gè)對(duì)象被引用時(shí)署海,提供一些額外的操作吗购,例如將對(duì)象被調(diào)用的次數(shù)記錄下來(lái)等。
二砸狞、示例
1)先創(chuàng)建一個(gè)BuySomething協(xié)議捻勉,協(xié)議有兩個(gè)買東西的方法,表示抽象主題角色趾代;
2)然后創(chuàng)建一個(gè)Person類贯底,遵守BuySomething協(xié)議,表示真實(shí)主題角色撒强;
3)最后創(chuàng)建一個(gè)Proxy類禽捆,里面有一個(gè)Person對(duì)象,也遵守BuySomething協(xié)議飘哨,表示代理主題角色胚想;
BuySomething協(xié)議:
@protocol BuySomething <NSObject>
- (void)buyLV; //購(gòu)買LV
- (void)buyChanel; //購(gòu)買香奈兒
@end
Person類:
@interface Person : NSObject<BuySomething>
@property (nonatomic, copy) NSString *name;
- (instancetype)initWithName:(NSString *)name;
@end
@implementation Person
- (instancetype)initWithName:(NSString *)name {
self = [super init];
if (self) {
_name = name;
}
return self;
}
- (void)buyLV {
NSLog(@"%@購(gòu)買了LV包包", self.name);
}
- (void)buyChanel {
NSLog(@"%@購(gòu)買了香奈兒香水", self.name);
}
@end
Proxy類:
// 代購(gòu)商
// .h文件
@interface Proxy : NSObject<BuySomething>
- (instancetype)initWithPerson:(Person *)person;
@end
// .m文件
@interface Proxy ()
@property (nonatomic, strong) Person *person;
@end
@implementation Proxy
- (instancetype)initWithPerson:(Person *)person {
self = [super init];
if (self) {
_person = person;
}
return self;
}
- (void)buyLV {
[self.person buyLV];
NSLog(@"%@買包包送手環(huán)", self.person.name); //可以增加額外的操作
}
- (void)buyChanel {
[self.person buyChanel];
}
@end
運(yùn)行代碼:
- (void)viewDidLoad {
[super viewDidLoad];
Person *xiaoHong = [[Person alloc] initWithName:@"小紅"];
Proxy *proxy1 = [[Proxy alloc] initWithPerson:xiaoHong];
[proxy1 buyChanel];
[proxy1 buyLV];
NSLog(@"--------------");
Person *xiaoFang = [[Person alloc] initWithName:@"小芳"];
Proxy *proxy2 = [[Proxy alloc] initWithPerson:xiaoFang];
[proxy2 buyChanel];
}
打印結(jié)果:
小紅購(gòu)買了香奈兒香水
小紅購(gòu)買了LV包包
小紅買包包送手環(huán)
--------------
小芳購(gòu)買了香奈兒香水
三、總結(jié)
? 代理模式為對(duì)象的間接訪問提供了一個(gè)解決方案芽隆,可以對(duì)對(duì)象的訪問進(jìn)行控制浊服。
1、優(yōu)點(diǎn)
共同優(yōu)點(diǎn):
1胚吁、能夠協(xié)調(diào)調(diào)用者和被調(diào)用者牙躺,在一定程度上降低了系統(tǒng)的耦合度。
2腕扶、客戶端可以針對(duì)抽象主題角色進(jìn)行編程孽拷,增加和更換代理類無(wú)須修改源代碼,符合開閉原則半抱,系統(tǒng)具有較好的靈活性和可擴(kuò)展性脓恕。
不同類型的代理模式的獨(dú)特優(yōu)點(diǎn):
1膜宋、遠(yuǎn)程代理為位于兩個(gè)不同地址空間對(duì)象的訪問提供了一種實(shí)現(xiàn)機(jī)制,可以將一些消耗資源較多的對(duì)象和操作移至性能更好的計(jì)算機(jī)上炼幔,提高系統(tǒng)的整體運(yùn)行效率秋茫。
2、虛擬代理通過一個(gè)消耗資源較少的對(duì)象來(lái)代表一個(gè)消耗資源較多的對(duì)象乃秀,可以在一定程度上節(jié)省系統(tǒng)的運(yùn)行開銷肛著。
3、緩沖代理為某一個(gè)操作的結(jié)果提供臨時(shí)的緩存存儲(chǔ)空間环形,以便在后續(xù)使用中能夠共享這些結(jié)果策泣,優(yōu)化系統(tǒng)性能,縮短執(zhí)行時(shí)間抬吟。
4萨咕、保護(hù)代理可以控制對(duì)一個(gè)對(duì)象的訪問權(quán)限,為不同用戶提供不同級(jí)別的使用權(quán)限火本。
2危队、缺點(diǎn)
1、由于在客戶端和真實(shí)主題之間增加了代理對(duì)象钙畔,因此有些類型的代理模式可能會(huì)造成請(qǐng)求的處理速度變慢茫陆,例如保護(hù)代理。
2擎析、實(shí)現(xiàn)代理模式需要額外的工作簿盅,而且有些代理模式的實(shí)現(xiàn)過程較為復(fù)雜,例如遠(yuǎn)程代理揍魂。
3午绳、適用場(chǎng)景
1栋豫、當(dāng)客戶端對(duì)象需要訪問遠(yuǎn)程主機(jī)中的對(duì)象時(shí)可以使用遠(yuǎn)程代理蝇棉。
2俐末、當(dāng)需要用一個(gè)消耗資源較少的對(duì)象來(lái)代表一個(gè)消耗資源較多的對(duì)象,從而降低系統(tǒng)開銷庄蹋、縮短運(yùn)行時(shí)間時(shí)可以使用虛擬代理瞬内,例如一個(gè)對(duì)象需要很長(zhǎng)時(shí)間才能完成加載時(shí)。
3限书、當(dāng)需要為某一個(gè)被頻繁訪問的操作結(jié)果提供一個(gè)臨時(shí)存儲(chǔ)空間虫蝶,以供多個(gè)客戶端共享訪問這些結(jié)果時(shí)可以使用緩沖代理。通過使用緩沖代理倦西,系統(tǒng)無(wú)須在客戶端每一次訪問時(shí)都重新執(zhí)行操作能真,只需直接從臨時(shí)緩沖區(qū)獲取操作結(jié)果即可。
4、當(dāng)需要控制對(duì)一個(gè)對(duì)象的訪問舟陆,為不同用戶提供不同級(jí)別的訪問權(quán)限時(shí)可以使用保護(hù)代理。
5耻矮、當(dāng)需要為一個(gè)對(duì)象的訪問(引用)提供一些額外的操作時(shí)可以使用智能引用代理秦躯。
4、iOS應(yīng)用舉例
? 大家都很熟悉UITableView的delegate和dataSource裆装,都是通過代理對(duì)象來(lái)控制對(duì)UITableView的訪問踱承。
Demo地址:iOS-Design-Patterns