程序员必知:代理模式简介与实现

简介: 程序员必知:代理模式简介与实现

iOS开发中有许多控件是没有addTarget:方法的,也无法通过control来拖放事件,如 UIPickerView。哥们我身边就有人有疑惑,那这个控件怎么监听值变化。看看官方文档(command点击UIPickerView)就可以看到,UIPickerView.h头文件中有这么一行

1 id _delegate;

要设置它的代理,说明UIPickerView本身并不需要知道自己的值改变时需要干点什么,而是交给它的代理去实现。于是我们在controller里实现UIPickerViewDelegate接口后,可以去实现这个方法

1 - (void)pickerView:(UIPickerView )pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;

来处理值变化后需要做什么事。哥们我这里有一个改编UIPickerView的值来实现各种键盘的代码,这里传上来给大家参考。

testForKeyboardType.zip 源代码下载

后面讲讲为何要使用delegate,使用delegate有什么好处。我这里写了一个delegate的实现,代码上传给大家

testprotocol.zip 源代码下载

我们用一个小剧情故事来说说为什么要用delegate模式来实现。

首先我们定义一个怪兽类Monster,这个Monster有一个方法,就是攻击人群。

然后我们定义了一个英雄类,英雄负责在怪兽出现时击杀怪兽。

通常大家的想法是,在英雄类中定义一个击杀的方法,参数是怪兽对象,然后由“怪兽攻击人群”的方法中调用“英雄击杀方法”,并把自己作为参数传入。大概代码如下:

1 //main.m

2 int main(int argc, const char argv【】)

3 {

4 @autoreleasepool{

5 Hero h1 = 【【Hero alloc】 init】;

6 Monster m1 = 【【Monster alloc】 init】;

7 m1.hero = h1;

8 【m1 dispearAndAttackHuman】;

9 }

10 return 0;

11 }

12

13 //monster.h

14 @property (nonatomic,strong) Hero hero;

15

16 //monster.m

17 - (void)dispearAndAttackHuman{

18 NSLog(@"怪兽出现了,并攻击了人类");

19 【hero killMonster:self】;

20 }//代码效果参考:http://www.ezhiqi.com/zx/art_1290.html

21

22 //hero.m

23 -(void)killMonster:(Monster) monster{

24 NSLog(@"英雄击杀了怪兽:%@",monster);

25 }

这样固然可以实现我们现在的需求,但如果情况发生了变化。击杀这个怪兽的可能是英雄,也有可能只是个NPC,还有可能是这个怪兽自己不小心摔死了。。。那我们就要改很多地方的代码来实现这个功能,大家想想是不是?

现在我们假定有一个object可以击杀这个怪兽,它可以是任何人、任何事物、甚至任何天气情况。。。但只要它有能力,那它就可以击杀这个怪兽!

首先我们来改编一下上面的代码的一部分

1 //monster.h

2 //@property (nonatomic,strong) Hero hero;

3 @property (nonatomic,strong)id delegate;

id可以作为任何对象来使用,这样就符合了我们初步的构想:任何对象都可以杀死怪兽。

然后,就要考虑我们之前说的另外一个条件了,就是这个对象必须拥有杀死怪兽的能力。

这个时候我们就需要引入一个协议,我们就把它当成是一个魔法契约。任何对象和这个魔法契约签订了协议,就可以拥有杀死怪兽的能力。

1 @protocol MonsterKillerDelegate

2

3 -(void)didMonsterDispeard:(Monster) monster;

4

5 @end

回头,我们将之前改的monster再修改一下

1 //monster.h

2 //@property (nonatomic,strong) Hero hero;

3 //@property (nonatomic,strong)id delegate;

4 @property (nonatomic,strong)id delegate;

5

6 //monster.m

7 - (void)dispearAndAttackHuman{

8 NSLog(@"怪兽出现了,并攻击了人类");

9 //【hero killMonster:self】;

10 【_delegate didMonsterDispeard:self】;

11 }//代码效果参考:http://www.ezhiqi.com/zx/art_6986.html

就这样,我们就把Monster和KillMonsterDelegate给定义好了,我们可以发现,这个协议和怪兽本身不再和英雄牵扯,怪兽有自己的方法(出现并攻击人类),然后通知符合协议的对象我出现了,想对我干什么我管不着,你自己看着办。怪兽本身不知道最后杀死它的是谁。

然后我们来实现这个协议,也就是和魔法契约签订协议。

1 //Hero.h

2 @interface Hero : NSObject //继承接口,签订协议

3

4 //Hero.m

5 //继承了MonsterKillDelegate就必须实现接口中的方法,这个方法就是拥有杀死怪兽的能力

6 -(void)didMonsterDispeard:(Monster) monster{

7 NSLog(@"英雄:%@ 击杀了怪兽:%@",self,monster);

8 }

这样这个英雄就拥有了杀死怪兽的能力,并且在实现协议的 didMonsterDispeard方法时杀死了怪兽(当然这里你也可以写成被怪兽杀死了)。

好!现在有新的需求了,出现了一个NPC门卫,他也要去杀怪兽,那我们可以如下实现

1 //NPC.h

2 @interface NPC : NSObject //实现接口

3

4 //NPC.m

5 -(void)didMonsterDispeard:(Monster) monster{

6 NSLog(@"NPC:%@ 击杀了怪兽:%@",self,monster);

7 }

好了,NPC也可以杀怪兽了,只要怪兽一出现就可以杀了它!

现在我们看看main函数怎么写。

1 Hero h1 = 【【Hero alloc】init】;

2 Monster *m1 = 【【Monster alloc】init】;

3 m1.delegate = h1; //Hero实现了MonsterKillDelegate

4 【m1 Dispear】;

5 //打印:

6 //怪兽:出现了

7 //英雄: 击杀了怪兽:

相关文章
|
2月前
|
设计模式 Java 程序员
谈谈代码:漫谈代理模式
代理模式是在编程中非常常见的设计模式.笔者在面试的过程中也经常会问到相关的问题,但是很多同学答的并不尽人意
59 0
谈谈代码:漫谈代理模式
|
2月前
|
设计模式 XML JSON
二十三种设计模式全面解析-代理模式进阶篇:揭秘远程代理
二十三种设计模式全面解析-代理模式进阶篇:揭秘远程代理
|
12月前
|
设计模式 缓存 Go
Go语言实现设计模式之代理模式
代理模式是一种常用的设计模式,它通过引入代理对象来控制对真实对象的访问。本文将详细介绍代理模式的概念和原理,并使用Go语言实现一个示例,以帮助读者更好地理解该设计模式的应用。
150 0
|
2月前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
|
1天前
|
程序员 iOS开发
程序员必知:代理模式简介与实现
程序员必知:代理模式简介与实现
|
设计模式 缓存 安全
深入浅出设计模式 - 代理模式
深入浅出设计模式 - 代理模式
11741 4
深入浅出设计模式 - 代理模式
|
12月前
|
设计模式 Go
Go语言实现设计模式之适配器模式
适配器模式是一种常用的设计模式,用于将一个类的接口转换成客户端所期望的另一种接口。本文将详细介绍适配器模式的概念和原理,并使用Go语言实现一个示例,以帮助读者更好地理解该设计模式的应用。
152 0
|
设计模式 监控 Java
代理模式看这一篇就够了~
代理模式看这一篇就够了~
657 1
代理模式看这一篇就够了~
|
设计模式 Java Maven
重学 Java 设计模式:实战装饰器模式
两个本想描述一样的意思的词,只因一字只差就让人觉得一个是好牛,一个好搞笑。往往我们去开发编程写代码时也经常将一些不恰当的用法用于业务需求实现中,但却不能意识到。一方面是由于编码不多缺少较大型项目的实践,另一方面是不思进取的总在以完成需求为目标缺少精益求精的工匠精神。
157 0
重学 Java 设计模式:实战装饰器模式
|
设计模式 Java
设计模式—— 十二 :代理模式
设计模式—— 十二 :代理模式
148 0
设计模式—— 十二 :代理模式