動(dòng)態(tài)代理模式的應(yīng)用很多,特別是在不能修改被代理類的前提下,要對(duì)執(zhí)行某些方法時(shí)需要打log或者捕捉異常等處理時(shí),是一個(gè)非常方便的方法。只需要少量修改客戶端(場(chǎng)景類)代碼和添加一個(gè)代理類就可以實(shí)現(xiàn),這個(gè)符合Open-Close PRinciple。
在java和.Net中的AOP也是利用了這種代理模式的實(shí)現(xiàn)。
iOS實(shí)現(xiàn)的代碼如下:
首先,定義一個(gè)接口,
@protocol DPDynamicProtocol <NSObject>@required- (void)doSomething;- (void)doOtherThing;@end
這個(gè)接口做兩件事,doSomething和doOtherThing。
被代理類需要實(shí)現(xiàn)這個(gè)接口(不實(shí)現(xiàn)其實(shí)也可以,只是設(shè)計(jì)不好,每一個(gè)類都應(yīng)該實(shí)現(xiàn)接口或者繼承自一個(gè)抽象類)。
#import "DPDynamicProtocol.h"@interface DPNormalObject : NSObject <DPDynamicProtocol>@end
@implementation DPNormalObject- (void)doSomething { NSLog(@"normal object do something");}- (void)doOtherThing { NSLog(@"normal object do other thing");}@end
同時(shí),代理類也實(shí)現(xiàn)DPDynamicProtocal接口,并且繼承自NSProxy這個(gè)類。
#import "DPDynamicProtocol.h"@interface DPDynamicProxy : NSProxy <DPDynamicProtocol> { @private id<DPDynamicProtocol> _obj;}- (id)initWithObject:(id<DPDynamicProtocol>)obj;@end
@implementation DPDynamicProxy- (id)initWithObject:(id<DPDynamicProtocol>)obj { _obj = obj; return self;}- (void)forwardInvocation:(NSInvocation *)invocation { if (_obj) { NSLog(@"proxy invocation obj method : %s", [invocation selector]); [invocation setTarget:_obj]; [invocation invoke]; }}- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { if ([_obj isKindOfClass:[NSObject class]]) { return [(NSObject *)_obj methodSignatureForSelector:sel]; } return [super methodSignatureForSelector:sel];}- (void)doSomething { NSLog(@"proxy do something");//1 [_obj doSomething];}@end
這樣,就可以很好的在被代理類NPNormalObject的doSomething方法前添加log或者捕捉異常了。
對(duì)于場(chǎng)景類的修改:
- (void)clientInvoke {// id<DPDynamicProtocol> obj = [[DPNormalObject alloc] init]; // 2 id<DPDynamicProtocol> obj = [[DPDynamicProxy alloc] initWithObject:[[DPNormalObject alloc] init]]; // 3 [obj doSomething]; [obj doOtherThing];}
只需要將2改為3即可。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注