iOS的動態代理模式的實現


動態代理模式的應用很多,特別是在不能修改被代理類的前提下,要對執行某些方法時需要打log或者捕捉異常等處理時,是一個非常方便的方法。只需要少量修改客戶端(場景類)代碼和添加一個代理類就可以實現,這個符合Open-Close Principle。

 

 

在Java和.Net中的AOP也是利用了這種代理模式的實現。

 

iOS實現的代碼如下:

首先,定義一個接口,

@protocol DPDynamicProtocol <NSObject>

@required
- (void)doSomething;
- (void)doOtherThing;

@end

這個接口做兩件事,doSomething和doOtherThing。

 

 

被代理類需要實現這個接口(不實現其實也可以,只是設計不好,每一個類都應該實現接口或者繼承自一個抽象類)。

 

#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


同時,代理類也實現DPDynamicProtocal接口,並且繼承自NSProxy這個類。

 

 

#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或者捕捉異常了。

 

 

對於場景類的修改:

 

- (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即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM