代理模式简介与实现 - delegate
2014-02-13 10:02
106 查看
iOS开发中有许多控件是没有addTarget:方法的,也无法通过control来拖放事件,如 UIPickerView。哥们我身边就有人有疑惑,那这个控件怎么监听值变化。看看官方文档(command点击UIPickerView)就可以看到,UIPickerView.h头文件中有这么一行
要设置它的代理,说明UIPickerView本身并不需要知道自己的值改变时需要干点什么,而是交给它的代理去实现。于是我们在controller里实现UIPickerViewDelegate接口后,可以去实现这个方法
来处理值变化后需要做什么事。哥们我这里有一个改编UIPickerView的值来实现各种键盘的代码,这里传上来给大家参考。
testForKeyboardType.zip 源代码下载
后面讲讲为何要使用delegate,使用delegate有什么好处。我这里写了一个delegate的实现,代码上传给大家
testprotocol.zip 源代码下载
我们用一个小剧情故事来说说为什么要用delegate模式来实现。
首先我们定义一个怪兽类Monster,这个Monster有一个方法,就是攻击人群。
然后我们定义了一个英雄类,英雄负责在怪兽出现时击杀怪兽。
通常大家的想法是,在英雄类中定义一个击杀的方法,参数是怪兽对象,然后由“怪兽攻击人群”的方法中调用“英雄击杀方法”,并把自己作为参数传入。大概代码如下:
这样固然可以实现我们现在的需求,但如果情况发生了变化。击杀这个怪兽的可能是英雄,也有可能只是个NPC,还有可能是这个怪兽自己不小心摔死了。。。那我们就要改很多地方的代码来实现这个功能,大家想想是不是?
现在我们假定有一个object可以击杀这个怪兽,它可以是任何人、任何事物、甚至任何天气情况。。。但只要它有能力,那它就可以击杀这个怪兽!
首先我们来改编一下上面的代码的一部分
id可以作为任何对象来使用,这样就符合了我们初步的构想:任何对象都可以杀死怪兽。
然后,就要考虑我们之前说的另外一个条件了,就是这个对象必须拥有杀死怪兽的能力。
这个时候我们就需要引入一个协议,我们就把它当成是一个魔法契约。任何对象和这个魔法契约签订了协议,就可以拥有杀死怪兽的能力。
回头,我们将之前改的monster再修改一下
就这样,我们就把Monster和KillMonsterDelegate给定义好了,我们可以发现,这个协议和怪兽本身不再和英雄牵扯,怪兽有自己的方法(出现并攻击人类),然后通知符合协议的对象我出现了,想对我干什么我管不着,你自己看着办。怪兽本身不知道最后杀死它的是谁。
然后我们来实现这个协议,也就是和魔法契约签订协议。
这样这个英雄就拥有了杀死怪兽的能力,并且在实现协议的 didMonsterDispeard方法时杀死了怪兽(当然这里你也可以写成被怪兽杀死了)。
好!现在有新的需求了,出现了一个NPC门卫,他也要去杀怪兽,那我们可以如下实现
好了,NPC也可以杀怪兽了,只要怪兽一出现就可以杀了它!
现在我们看看main函数怎么写。
id<UIPickerViewDelegate> _delegate;
要设置它的代理,说明UIPickerView本身并不需要知道自己的值改变时需要干点什么,而是交给它的代理去实现。于是我们在controller里实现UIPickerViewDelegate接口后,可以去实现这个方法
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;
来处理值变化后需要做什么事。哥们我这里有一个改编UIPickerView的值来实现各种键盘的代码,这里传上来给大家参考。
testForKeyboardType.zip 源代码下载
后面讲讲为何要使用delegate,使用delegate有什么好处。我这里写了一个delegate的实现,代码上传给大家
testprotocol.zip 源代码下载
我们用一个小剧情故事来说说为什么要用delegate模式来实现。
首先我们定义一个怪兽类Monster,这个Monster有一个方法,就是攻击人群。
然后我们定义了一个英雄类,英雄负责在怪兽出现时击杀怪兽。
通常大家的想法是,在英雄类中定义一个击杀的方法,参数是怪兽对象,然后由“怪兽攻击人群”的方法中调用“英雄击杀方法”,并把自己作为参数传入。大概代码如下:
//main.m int main(int argc, const char * argv[]) { @autoreleasepool{ Hero *h1 = [[Hero alloc] init]; Monster *m1 = [[Monster alloc] init]; m1.hero = h1; [m1 dispearAndAttackHuman]; } return 0; } //monster.h @property (nonatomic,strong) Hero* hero; //monster.m - (void)dispearAndAttackHuman{ NSLog(@"怪兽出现了,并攻击了人类"); [hero killMonster:self]; } //hero.m -(void)killMonster:(Monster*) monster{ NSLog(@"英雄击杀了怪兽:%@",monster); }
这样固然可以实现我们现在的需求,但如果情况发生了变化。击杀这个怪兽的可能是英雄,也有可能只是个NPC,还有可能是这个怪兽自己不小心摔死了。。。那我们就要改很多地方的代码来实现这个功能,大家想想是不是?
现在我们假定有一个object可以击杀这个怪兽,它可以是任何人、任何事物、甚至任何天气情况。。。但只要它有能力,那它就可以击杀这个怪兽!
首先我们来改编一下上面的代码的一部分
//monster.h //@property (nonatomic,strong) Hero* hero; @property (nonatomic,strong)id delegate;
id可以作为任何对象来使用,这样就符合了我们初步的构想:任何对象都可以杀死怪兽。
然后,就要考虑我们之前说的另外一个条件了,就是这个对象必须拥有杀死怪兽的能力。
这个时候我们就需要引入一个协议,我们就把它当成是一个魔法契约。任何对象和这个魔法契约签订了协议,就可以拥有杀死怪兽的能力。
@protocol MonsterKillerDelegate <NSObject> -(void)didMonsterDispeard:(Monster*) monster; @end
回头,我们将之前改的monster再修改一下
//monster.h //@property (nonatomic,strong) Hero* hero; //@property (nonatomic,strong)id delegate; @property (nonatomic,strong)id<MonsterKillerDelegate> delegate; //monster.m - (void)dispearAndAttackHuman{ NSLog(@"怪兽出现了,并攻击了人类"); //[hero killMonster:self]; [_delegate didMonsterDispeard:self]; }
就这样,我们就把Monster和KillMonsterDelegate给定义好了,我们可以发现,这个协议和怪兽本身不再和英雄牵扯,怪兽有自己的方法(出现并攻击人类),然后通知符合协议的对象我出现了,想对我干什么我管不着,你自己看着办。怪兽本身不知道最后杀死它的是谁。
然后我们来实现这个协议,也就是和魔法契约签订协议。
//Hero.h @interface Hero : NSObject <MonsterKillerDelegate> //继承接口,签订协议 //Hero.m //继承了MonsterKillDelegate就必须实现接口中的方法,这个方法就是拥有杀死怪兽的能力 -(void)didMonsterDispeard:(Monster*) monster{ NSLog(@"英雄:%@ 击杀了怪兽:%@",self,monster); }
这样这个英雄就拥有了杀死怪兽的能力,并且在实现协议的 didMonsterDispeard方法时杀死了怪兽(当然这里你也可以写成被怪兽杀死了)。
好!现在有新的需求了,出现了一个NPC门卫,他也要去杀怪兽,那我们可以如下实现
//NPC.h @interface NPC : NSObject <MonsterKillerDelegate> //实现接口 //NPC.m -(void)didMonsterDispeard:(Monster*) monster{ NSLog(@"NPC:%@ 击杀了怪兽:%@",self,monster); }
好了,NPC也可以杀怪兽了,只要怪兽一出现就可以杀了它!
现在我们看看main函数怎么写。
Hero *h1 = [[Hero alloc]init]; Monster *m1 = [[Monster alloc]init]; m1.delegate = h1; //Hero实现了MonsterKillDelegate [m1 Dispear]; //打印: //怪兽:<Monster: 0x100203ad0>出现了 //英雄:<Hero: 0x100202980> 击杀了怪兽:<Monster: 0x100203ad0>
相关文章推荐
- Unity3D 利用C#实现简单的代理模式Delegate(委托)
- SSM框架day01——025——CGLIB动态代理模式、026——CGLIB动态代理模式的实现、027——CGLIB动态代理执行流程分析、CGLIB动态代理的MethodProxy参数
- 静态代理模式、动态代理模式(实现、对比)
- iOS代理模式实现原理
- 设计模式C++实现(8)——代理模式
- java反射机制(三)---java的反射和代理实现IOC模式 模拟spring
- 设计模式C++实现(8)——代理模式
- 反射实现 AOP 动态代理模式(Spring AOP 的实现 原理)
- 设计模式C++实现(8)——代理模式
- 代理模式通用模板实现
- 设计模式之动态代理(Java的JDK动态代理实现)
- 【Unity】使用C#中的委托类型实现代理设计模式
- 详解设计模式中的proxy代理模式及在Java程序中的实现
- 大话设计模式C++实现-第7章-代理模式
- 采用ajp代理模式配置Apache+tomcat实现负载均衡
- Unity3D 游戏引擎之利用C#实现代理模式
- 反射实现AOP动态代理模式(SpringAOP的实现原理)
- 静态代理模式实现
- 代理模式(一):代理模式概述,代理模式结构与实现
- 如何从response里面取出向客户端输出的html流-代理模式实现