zoukankan      html  css  js  c++  java
  • 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即可。

  • 相关阅读:
    使用JS实现图片轮播滚动跑马灯效果
    特殊字符和注释标签
    html常用标签总结
    html重点标签总结
    web常用开发工具
    标签分类和关系
    Web标准和骨架
    常用开浏览器内核
    常用浏览器介绍
    2019/08/20记
  • 原文地址:https://www.cnblogs.com/ios8/p/ios-daili.html
Copyright © 2011-2022 走看看