代理模式:一个对象让另一个对象替他执行一定的动作。
就是你想做一件事但不想自己去做,你就需要制定一个代理,让这个代理帮忙去做,体现在代码上就是声明一个代理对象作为成员变量。需要作某些事情的时候调用该代理对象的方法。
下面的例子是住人想看电影需要知道电影票的相关信息,但是主人很懒,需要让仆人帮忙去搜集相关的信息将结果告诉住人。
Person.h
@interface Person : NSObject
@property (nonatomic,strong) Servant * delegate;
- (void) buyTicket;
@end
Person.m
@implementation Person
- (void) buyTicket{
NSLog(@"票价为%d的票还剩余%d张",[_delegate ticketprice],[_delegate leftTicketCount]);
}
@end
Servant.h
@interface Servant : NSObject
- (int) ticketprice;
- (int) leftTicketCount;
@end
Servant.m
@implementation Servant
- (int)ticketprice
{
//.....
return 1;
}
- (int)leftTicketCount
{
//.....
return 1000;
}
@end
Main
int main(int argc, const char * argv[])
{
Person *p = [[Person alloc] init];
Servant *s = [[Servant alloc]init];
p.delegate = s;
[p buyTicket];
return 0;
}
打印:票价为1的票还剩余1000张
上面的代码虽然实现了这个功能,但是存在的问题是代码之间的耦合性太高。如果Servant类改变了,相应的需要修改Person类的内容。在iOS中通过协议实现代理。
想要减弱代码的耦合性,首先考虑Person类中声明的代理对象指针为万能指针而不是仅仅局限于限定某种类型的类,这样修改代理的类就不需要更改本类的内容。
即下面的代码声明
@property (nonatomic,strong) Servant * delegate;
改为
@property (nonatomic,strong) id delegate;
显然这样会导致Person.m类中的方法调用出错,因为_delegate成员是id类型的,编译器不知道他的方法有哪些。
因此可以将这两个方法抽成协议,在声明代理变量的时候限定其需要实现该协议,这样就不会报方法找不到的错误了,即:
@property (nonatomic,strong) id<TicketDelegate> delegate;
Person.h
@interface Person : NSObject
@property (nonatomic,strong) id<TicketDelegate> delegate;
- (void) buyTicket;
@end
TicketDelegate.h
@protocol TicketDelegate <NSObject>
@required
- (int) ticketprice;
- (int) leftTicketCount;
@end
Servant1.h
//Servant1类实现TicketDelegate协议
@interface Servant1 : NSObject < TicketDelegate >
@end
Servant1.m
@implementation Servant1
- (int)ticketprice
{
//.....
return 1;
}
- (int)leftTicketCount
{
//.....
return 1000;
}
@end
这样,当需要更换代理的时候就不需要修改Person类里面的代理对象的的声明,减少代码之间的耦合度。另外,目前感觉代理和回调有很大的相似之处,只是关注的角度不一样。