iOS的动态代理模式的实现

动态代理模式的应用很多,特别是在不能修改被代理类的前提下,要对执行某些方法时需要打log或者捕捉异常等处理时,是一个非常方便的方法。只需要少量修改客户端(场景类)代码和添加一个代理类就可以实现,这个符合Open-Close Principle。

在Java和.Net中的AOP也是利用了这种代理模式的实现。


iOS实现的代码如下:

首先,定义一个接口,

@protocol DPDynamicProtocol 

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

@end
这个接口做两件事,doSomething和doOtherThing。


被代理类需要实现这个接口(不实现其实也可以,只是设计不好,每一个类都应该实现接口或者继承自一个抽象类)。

#import "DPDynamicProtocol.h"

@interface DPNormalObject : NSObject 

@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  {
    
    @private
    id _obj;
}

- (id)initWithObject:(id)obj;

@end

@implementation DPDynamicProxy

- (id)initWithObject:(id)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 obj = [[DPNormalObject alloc] init];    //  2
    id obj = [[DPDynamicProxy alloc] initWithObject:[[DPNormalObject alloc] init]];  //  3
    
    [obj doSomething];
    [obj doOtherThing];
}

只需要將2改为3即可。


你可能感兴趣的:(设计模式)