标签:
比如现在有一个人,想要买一张电影票,但是她很忙碌,没时间去买,那怎么办呢?只能说委托给另一个人去买。
此时,需要 person 给 other 发送消息,通知 other 去给她买电影票,而 other 也要反馈消息给 person,此时 other 就是一个代理人,person 委托代理人去办事情(买票)。代理人是给委托人代办一些事情的人。具体代理人怎么做的这些事情,委托人不管,委托人只看反馈。
先看代理设计模式的基本原理
#import <Foundation/Foundation.h> #import "Agent.h" @interface Person : NSObject - (void) buyTicket; // 拥有一个代理属性 @property (nonatomic, retain) Agent delegate; @end
一个委托人的类,person 类和 person 类的实现
#import "Person.h" @implementation Person // 买电影票 - (void)buyTicket { // 叫代理去帮自己买票(询问一下票价、询问一下票的剩余张数) double price = [_delegate ticketPrice]; int number = [_delegate leftTicketsNumber]; NSLog(@"通过代理的帮忙,票价=%f,还剩%d张票", price, number); } - (void)dealloc { [_delegate release]; [super dealloc]; } @end
其中,委托人不亲自去买票,而是让代理人去买票,而具体代理人怎么去办事,委托人不去关心。只需要在委托类里去调对应的代理实现的方法即可。
下面是代理类的实现,其中有代理代办的事情,需要查询剩余票数,和询问票价单价。这些都不需要委托人去做,而是代理给一一代办。
#import "Agent.h" @implementation Agent // 剩余的票数 - (int)leftTicketsNumber { // ... 亲自跑电影院\或者打电话 return 1; } // 每一张票多少钱 - (double)ticketPrice { // ... 亲自跑电影院\或者打电话 return 1000; } @end
在主方法里,委托人对象 p,p 想去买电影票,但是没时间买,那么好了,让代理去代办这个事情吧,具体怎么办,不管他,只要能买回票就行。然后代理对象 a 。接下来,把代理对象 a 赋值给委托对象 p 的_delegate 成员。然后开始调用买票的方法。
#import <Foundation/Foundation.h> #import "Person.h" #import "Agent.h" int main(int argc, const char * argv[]) { @autoreleasepool { Person *p = [[Person alloc] init]; Agent *a = [[Agent alloc] init]; p.delegate = a; [p buyTicket]; } return 0; }
这样基本上实现了代理设计模式的思路,需要一个委托类的对象p,一个代理类的对象 a,在委托类里声明了代理类的对象delegate,然后把代理类的对象 a 传入委托类 b 中的 delegate,最后让p 给 a 发送消息,本质也就是让 p去调用 a 的方法(使用 p 内的 delegate 调用的 a 的方法)去执行 p 本来想执行的事务。但是,这样的写法,非常不规范,不符合低耦合高内聚的原则!继续分析:
比如,我们把 Agent 类删掉或者哪怕换个名字,那么以后在使用这个代理模式,Person 类就无法发挥作用,就失去了代理设计模式的功能,如果非要用,就需要改变这个架构的代码,尤其是不仅仅需要改变代理类的代码,麻烦的是每次还要修改委托类的代码。这样的话麻烦很大!因为,person类直接依赖了 agent 类。这会使得程序变得耦合度很高!
需要改进代理设计模式:
1、类名不能写死!iOS 中需要使用 id类型(万能指针)代替类类型
2、联想 oc 中的协议语法,需要定义一个协议。因为如果 person 仅仅满足 id 类型,但是不能保证程序知道这个对象里面有什么方法或者属性,那么可以使用协议,只要满足这个协议,那么就可以做我的代理。
3、这样搞,完全是低耦合的设计。要求换代理的时候,仅仅需要增加新的代理累即可,或者删除代理的时候,删除即可。而每次的委托类的代码无需做出任何改变即可满足。
如图所示,代理在给人办事情的时候,不是说,想办就可以办,或者说谁想来都能办的,必须要遵循一份我们提供的协议!因为,不遵循协议,鬼知道代理里面有什么方法或者属性呢?你能办什么事情,人都不知道!故必须遵循一份提供的协议,告诉人,代理可以做什么,具体怎么去做,那都是代理的事情了。人不用关心过程,只看结果,事情是办了,还是没办。而人的内部,为了低耦合的实现,把 agent 类型的对象,换成 id 类型,然后让它遵循协议即可。这样就实现了低耦合!代码如下:
#import <Foundation/Foundation.h> #import "TicketDelegate.h" @interface Person : NSObject - (void) buyTicket; // 拥有一个代理属性 // id代表代理的类名随便 // 但必须遵守TicketDelegate协议 @property (nonatomic, retain) id<TicketDelegate> delegate; @end
下面是person 的 m 文件
#import "Person.h" @implementation Person // 买电影票 - (void)buyTicket { // 叫代理去帮自己买票(询问一下票价、询问一下票的剩余张数) double price = [_delegate ticketPrice]; int number = [_delegate leftTicketsNumber]; NSLog(@"通过代理的帮忙,票价=%f,还剩%d张票", price, number); } - (void)dealloc { [_delegate release]; [super dealloc]; } @end
下面是协议的代码,只需要声明一些方法即可。
#import <Foundation/Foundation.h> // 声明一些方法 @protocol TicketDelegate <NSObject> // 返回票价 - (double) ticketPrice; // 还剩多少张票 - (int) leftTicketsNumber; @end
下面增加一个新的代理类 nextagent,这个代理类,需要遵守这份委托人提供的协议。
#import <Foundation/Foundation.h> #import "TicketDelegate.h" @interface NextAgent : NSObject<TicketDelegate> @end
新代理的实现。
#import "NextAgent.h" @implementation NextAgent - (double)ticketPrice { return 500; } - (int)leftTicketsNumber { return 10; } @end
在 iOS 中的实际应用很多地方都使用了代理设计模式
比如 qq 聊天的表格,是一行行的,或者淘宝客户端展示产品的列表。如下 qq 聊天列表,左边一个头像,右边一般是两行,第一行是昵称,第二行是最近的一段聊天记录显示。
整个的屏幕的表格是table,table 里面很多的行,显式的很多行的数据,table 本身不去做这些事情,而是表格控件去做—UITableView很常用的控件,这个控件里面有个 id 类型的数据源 datasource,也就是任何人都能做它的数据元,,但是前提是必须遵守一份它规定的协议——UITableViewDataSource 协议,里面很多方法。这就是代理设计模式的使用。
标签:
原文地址:http://www.cnblogs.com/kubixuesheng/p/4375133.html