委托(代理)模式在iOS应用中可谓"遍地开花",不仅在我们的应用中会大量的使用它,即便是在Cocoa Touch框架中也得到了广泛的应用。
提出问题
以应用生命周期为非运行状态的应用启动场景举例来说,启动的过程如下图所示:
假设这一系列处理上都是在’上帝类’UIApplication中完成。"上帝类"不是很友好,需要重构。其实在编程中,要尽量避免使用"上帝类",因为它高度耦合,职责不清,难以维护。其实iOS中protocol和category的引入就是为了去除类上帝类的使用,也是面向接口编程思想的体现**.总而言之,我们按照职责将上帝类拆分到各自类中或category中。
幸运的是,Applem没有把UIApplication类设计成"上帝类",而是将其分割成了两个不同的角色类,一个是框架类,框架类具有通用,可重复使用,与具体应用无关的特性。另一个扮演应用角色类,与具体应用相关。应用类常常被设计成’协议‘,在JAVA中叫做"接口",开发人员需要在具体应用中实现该协议。
如下图,将一些功能提取出来放在application:didFinishLaunchingWithOptions:和aplicationDidBecomeActive:方法中完成,定义在UIApplicationDelegate这样UIApplication就变成了框架类:
具体使用时,需要实现UIApplicationDelegate协议,如下图:
所以我们在创建应用时,总有AppleDelegate这个委托类.
实现原理
我们举一个古希腊哲学家的例子:这个哲学家毕生只做三件事’睡觉’,’吃饭’和’工作’.为了更好地生活,提高工作效率,他要把这些这些事情委托给他的徒弟。然而要成为他的徒弟,就必须实现一个协议,该协议能够处理’睡觉’,’吃饭’和’工作’的问题,三者关系如下:
从图中看出,通用类Philosopher声明了PhilosopherDelegate,之后DiscipleViewController实现了这个协议。
下面我们看看PhilosopherDelegate实现代码:
@protocol PhilosopherDelegate
@required
- (void) sleep;
- (void) eat;
- (void) work;
@end
@implementation DiscipleViewController
- (void) sleep
{
NSLog("sleep");
}
- (void) eat
{
NSLog("eat");
}
- (void) work
{
NSLog("work");
}
@end
通用类通过声明一个delegate,并设置Philosopher.delegate=self来与委托对象建立联系.之后使用[Philosopher.delete sleep]调用委托对象的方法实现.
基本的代理模式就讲完了,其实用block或者notification都可以代替代理模式,具体的使用要依据具体情况而定.要是层数太多,不如使用Notification来做.