动态代理模式的应用很多,特别是在不能修改被代理类的前提下,要对执行某些方法时需要打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. input 控件监听回车确认按钮。

    前端开发的同学捕捉回车按键经常会用到 if(event.keyCode == 13){ console.log("点击了回车按键");} 但是在微信上面,我们一般会用到指令 bin ...

  2. 仿ElementUI构建自己的Vue组件库用babel-plugin-component按需加载组件及自定义SASS主题

    最近使用ElementUI做项目的时候用Babel的插件babel-plugin-component做按需加载,使得组件打包的JS和CSS包体积大大缩小,加载速度也大大提升,所有想模仿做一个组件库也来 ...

  3. python__new__与__init__的区别

    __new__ __init__区别 1 class A(object): 2 def __init__(self,*args, **kwargs): 3 print "init A&quo ...

  4. [WEB面试题] web前端面试题JavaScript第一弹,个人整理部分面试题汇总

    以下内容仅供参考,成年人不讲对错只讲利弊 1.什么是JavaScript原型链?如何理解 JavaScript中的每个对象都有一个prototype属性,我们称之为原型 原型的值是一个对象有自己的原型 ...

  5. React-Native开发之原生模块封装(Android)升级版

     本文主题:如何实现原生代码的复用,即如何将原生模块封装. (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/52862 ...

  6. Keras & Theano 输出中间层结果

    Keras & Theano get output of an intermediate layer 1.使用函数模型API,新建一个model,将输入和输出定义为原来的model的输入和想要 ...

  7. ios虚拟机安装(一)

    安装软件:vmwarestation-v9.0.1()   MAC OS X Mountain Lion 10.8.2 xcode 4.6.2 一定要安装补丁:unlock-all-v110(mac系 ...

  8. ReactJS表单handleChange

    handleInputChange = (event) => { const target = event.target; const type = target.type; const val ...

  9. Ad-hoc 查询以及动态SQL的罪恶[译]

    本文为翻译文章,原文地址:https://www.simple-talk.com/blogs/2009/08/03/stolen-pages-ad-hoc-queries-and-the-sins-o ...

  10. machine learning model(algorithm model) .vs. statistical model

    https://www.analyticsvidhya.com/blog/2015/07/difference-machine-learning-statistical-modeling/ http: ...