动态代理模式的应用很多,特别是在不能修改被代理类的前提下,要对执行某些方法时需要打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即可。

https://www.cnblogs.com/ios8/p/ios-daili.html

NSProxy应用例子的更多相关文章

  1. iOS Class 使用NSProxy和NSObject设计代理类的差异

    经常发现在一些需要使用消息转发而创建代理类时, 不同的程序员都有着不同的使用方法, 有些采用继承于NSObject, 而有一些采用继承自NSProxy. 二者都是Foundation框架中的基类, 并 ...

  2. 使用NSProxy和NSObject设计代理类的差异

    经常发现在一些需要使用消息转发而创建代理类时, 不同的程序员都有着不同的使用方法, 有些采用继承于NSObject, 而有一些采用继承自NSProxy. 二者都是Foundation框架中的基类, 并 ...

  3. SQLServer地址搜索性能优化例子

    这是一个很久以前的例子,现在在整理资料时无意发现,就拿出来再改写分享. 1.需求 1.1 基本需求: 根据输入的地址关键字,搜索出完整的地址路径,耗时要控制在几十毫秒内. 1.2 数据库地址表结构和数 ...

  4. C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)

    第一次接触HtmlAgilityPack是在5年前,一些意外,让我从技术部门临时调到销售部门,负责建立一些流程和寻找潜在客户,最后在阿里巴巴找到了很多客户信息,非常全面,刚开始是手动复制到Excel, ...

  5. REGEX例子

    作为REGEX的例子,代码9.3显示了一个给定的文件有多少行,具有给定的模式,通过命令行输入(注:有更有效率的方式来实现这个功能,如Unix下的grep命令,在这里只是给出了另一种方式).这个程序像下 ...

  6. CSharpGL(25)一个用raycast实现体渲染VolumeRender的例子

    CSharpGL(25)一个用raycast实现体渲染VolumeRender的例子 本文涉及的VolumeRendering相关的C#代码是从(https://github.com/toolchai ...

  7. 简单例子了解View的事件分发

    什么是事件分发 我们在写自定义ViewGroup或者自定义View的时候经常要处理用户的点击事件,如果我们的View在最底层,他在很多ViewGroup里面,我们如何让我们的点击事件准确传递到View ...

  8. 简单的例子了解自定义ViewGroup(一)

    在Android中,控件可以分为ViewGroup控件与View控件.自定义View控件,我之前的文章已经说过.这次我们主要说一下自定义ViewGroup控件.ViewGroup是作为父控件可以包含多 ...

  9. kqueue例子

    网络服务器通常都使用epoll进行异步IO处理,而开发者通常使用mac,为了方便开发,我把自己的handy库移植到了mac平台上.移植过程中,网上居然没有搜到kqueue的使用例子,让我惊讶不已.为了 ...

随机推荐

  1. 读取配置文件-AppConfig

    using System.Xml; using System.IO; using System; namespace Framework.Common { /// <summary> // ...

  2. 五:Jquery-demo

    一:多选框的全选与全不选 1.遍历:使用each(); $("#checkallbox").click(function(){ var isChecked = this.check ...

  3. 请整体描述Java异常体系

    java把异常当做对象来处理,并定义一个基类Throwable作为所有异常的超类.在java API中已经定义了许多异常的类,这些异常分为两大类,错误Error和异常Exception.其中异常Exc ...

  4. DHU 1788 Chinese remainder theorem again 中国剩余定理

    Chinese remainder theorem again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 ...

  5. MarkDownPad 专业汉化破解

     解压Pa_ttrar 运行Pa_ttrar.exe    点击下边第一个按钮“patch”——>弹出窗选择“YES”  选择“YES”后会选择一个文件,找到“C:\Users\用户名\AppD ...

  6. Linux学习7-Linux常用命令(3)

    文件处理命令         命令名称:touch 命令英文原意:touch 命令所在路径:/bin/touch 执行权限:所有用户 功能描述:创建空文件 语法:touch[文件名] 范例: $tou ...

  7. C#(简单递归)和实现IComparable接口

    递归: using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syst ...

  8. webstorm修改文件,webpack-dev-server及roadhog不会自动编译刷新

    转自:http://www.cnblogs.com/ssrsblogs/p/6155747.html 重装了 webstorm ,从10升级到了2016 一升不要紧,打开老项目,开启webpakc-d ...

  9. Week5——Ajax

    1.简介 AJAX 相当于异步 JavaScript 和 XML,是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网 ...

  10. 混淆矩阵(Confusion matrix)的原理及使用(scikit-learn 和 tensorflow)

    原理 在机器学习中, 混淆矩阵是一个误差矩阵, 常用来可视化地评估监督学习算法的性能. 混淆矩阵大小为 (n_classes, n_classes) 的方阵, 其中 n_classes 表示类的数量. ...