当前位置: 首页 > news >正文

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

相关文章:

  • 关于volatile
  • 通过vbs脚本备份数据-本地到异地
  • 动态SQL和静态SQL
  • hadoop集群监控工具ambari安装
  • MVC 区分是哪按键提交FORM
  • UML画图总结以及浅谈UNL九种图
  • LAMP+extmail+postfix+dovecot
  • 修复被破坏了的linux文件系统分区表
  • poj2488 A Knight's Journey 简单DFS 注意搜索步骤
  • ProgressBar
  • linux 学习(三) php相关
  • 欧拉计划的Python解法(1-10)
  • SharePoint 网站登录不上,3次输入用户名/密码白页、
  • 关于C语言指针几个容易混淆的概念
  • 八一八android开发规范(一种建议)
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • Bytom交易说明(账户管理模式)
  • css选择器
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • IP路由与转发
  • JSONP原理
  • mysql 数据库四种事务隔离级别
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Python语法速览与机器学习开发环境搭建
  • Redux 中间件分析
  • sessionStorage和localStorage
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • windows下mongoDB的环境配置
  • 聚簇索引和非聚簇索引
  • 理清楚Vue的结构
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 写给高年级小学生看的《Bash 指南》
  • # Panda3d 碰撞检测系统介绍
  • # 数据结构
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (四)Controller接口控制器详解(三)
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (转)Mysql的优化设置
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转)视频码率,帧率和分辨率的联系与区别
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET 5种线程安全集合
  • .NET Core 版本不支持的问题
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .net 简单实现MD5
  • .NET 命令行参数包含应用程序路径吗?
  • .net安装_还在用第三方安装.NET?Win10自带.NET3.5安装
  • .NET企业级应用架构设计系列之结尾篇
  • .NET实现之(自动更新)