標籤:
代理模式有的時候也被稱之為委託模式,但是實際上兩者是有分別的,代理模式為另一個對象提供一個替身或預留位置訪問這個對象,代理對象和控制訪問對象屬於同一類,委派物件和對象不一定屬於同一類。兩者都可以控制類的訪問,訪問代理的方法A也就意味著訪問對象的方法A,訪問委派物件方法A執行的是可以是對象的方法B。從實際開發的角度看,委託屬於代理模式的擴大版,並沒有那麼多的限制。
基礎知識
代理模式相對比較簡單,可以簡單的看一下UML類圖:
代理模式以便管理客戶對對象的訪問,管理訪問的方式有很多種。遠程代理管理客戶和遠程對象之間的互動,虛擬代理控制方式執行個體開銷大的對象,代理模式和裝飾者模式有點相似,裝飾者模式為對象加上行為,代理模式控制對另一個對象的訪問。
實戰研究
我們就根據上面的UML的類圖寫一個比較常規的例子,先定義定義Subject:
@protocol SubjectProtocol<NSObject>-(void)displayImage;@end@interface Subject : NSObject<SubjectProtocol>@end
Proxy中的subject屬性相當於UML中的delegate指向了真實對象的引用:
@interface SubjectProxy()@property (strong,nonatomic) Subject *subject;@property (strong,nonatomic) NSString *fileName;@end@implementation SubjectProxy-(instancetype)initWithFileName:(NSString *)fileName{ self=[super init]; if (self) { self.fileName=fileName; } return self;}-(void)displayImage{ if (!self.subject) { self.subject=[[RealSubject alloc]initWithFileName:self.fileName]; } [self.subject displayImage];}@end
RealSubject的實現:
@interface RealSubject()@property (strong,nonatomic) NSString *fileName;@end@implementation RealSubject-(instancetype)initWithFileName:(NSString *)fileName{ self=[super init]; if (self) { self.fileName=fileName; } return self;}-(void)loadFromDisk{ NSLog(@"Loading--%@",self.fileName);}-(void)displayImage{ NSLog(@"Display--%@",self.fileName);}@end
調用:
Subject *sub=[[SubjectProxy alloc]initWithFileName:@"部落格園-FlyElephant"]; Subject *proxy=[[SubjectProxy alloc]initWithFileName:@"Book"]; [sub displayImage]; [proxy displayImage];
輸出:
2016-01-19 08:22:28.305 iOS[24822:5266030] Display--部落格園-FlyElephant2016-01-19 08:22:28.305 iOS[24822:5266030] Display--Subject---Book
iOS開發中我們對委託用的比較多,理解代理模式也很容易,代理在Objective-C中有一種更重要的例子是用於引用計數指標對象,當一個複雜物件的多份副本須存在時,代理模式可以結合享元模式以減少儲存空間用量。典型作法是建立一個複雜物件及多個代理者,每個代理者會引用到原本的複雜物件。而作用在代理者的運算會轉送到原本對象。一旦所有的代理者都不存在時,複雜物件會被移除。
關於iOS中的委託如果不熟悉可以參考本文之前的iOS開發-委託實戰~
iOS開發-代理模式