委托模式从GoF装饰模式、适配器模式和模板方法等演变过来,几乎每一个应用都会或多或少的用到委托模式。
在古希腊有一个哲学家,他毕生只做三件事情:“睡觉”、“吃饭”、和“工作”。为了更好的生活,提高工作效率,他会找一个徒弟,把这些事情委托给他弟弟做。然而要成为他得徒弟,需要实现一个协议,协议要求能够实现“睡觉”、“吃饭”、“工作”的问题。三者的关系如下。
从图中可以看到,通用类(Philosopher)保持指向委托对象(ViewController)的“弱引用”
(id<PhilosopherDelegate> delegate),委托对象(ViewController)就是哲学家的“徒弟”,它实现了协议
PhilosopherDelegate。PhilosopherDelegate规定了3个方法:sleep、eat、work;
代码PhilosopherDelegate.h的代码如下
@protocol PhilosopherDelegate @requied
- (void) sleep;
- (void) eat;
- (void) work; @end
可以看到PhilosopherDelegate定义了三个方法。如果改委托协议没有m文件。它的定义可以放在别的h文件中。他得实现委托类ViewController,相关代码如下:
//
// ViewController.h
// Philosopher
//
// Created by ChenHao on 10/30/14.
// Copyright (c) 2014 xxTeam. All rights reserved.
// #import <UIKit/UIKit.h>
#import "PhiosopherDelegate.h"
#import "Phiosopher.h"
@interface ViewController : UIViewController<PhiosopherDelegate> @end //
// ViewController.m
// Philosopher
//
// Created by ChenHao on 10/30/14.
// Copyright (c) 2014 xxTeam. All rights reserved.
// #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
Phiosopher *obj=[[Phiosopher alloc] init];
obj.delegate=self;
[obj start];
} -(void)sleep
{
NSLog(@"sleep");
}
-(void)eat
{
NSLog(@"eat");
}
-(void)work
{
NSLog(@"work");
} @end
委托对象如何于通用类建立引用关系呢?我们通过ViewController方法中得obj.delegate=self 语句来指定委托对象和通用类结构的引用关系。一半情况下,通用类由框架直接提供。在这个例子中,我们根据需要自己实现了通用类。
代码如下
//
// Phiosopher.h
// Philosopher
//
// Created by ChenHao on 10/30/14.
// Copyright (c) 2014 xxTeam. All rights reserved.
// #import <Foundation/Foundation.h>
#import "PhiosopherDelegate.h"
@interface Phiosopher : NSObject
{
NSTimer *timer;
int count;
} @property (nonatomic,weak) id<PhiosopherDelegate> delegate;
-(void)start;
-(void)handle;
@end
在上述代码中,我们定义了delegate属性,它的类型食id《PhiosopherDelegate》,他可以保存委托对象的引用,其中属性weak说明是弱引用,这里是弱引用是为了防止内存引用计数增加二导致委托对象无法释放的问题。
//
// Phiosopher.m
// Philosopher
//
// Created by ChenHao on 10/30/14.
// Copyright (c) 2014 xxTeam. All rights reserved.
// #import "Phiosopher.h" @implementation Phiosopher -(void)start
{
count=0;
timer=[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(handle) userInfo:nil repeats:YES];
} -(void)handle
{
switch (count) {
case 0:
[self.delegate sleep];
count++;
break;
case 1:
[self.delegate eat];
count++;
break;
case 2:
[self.delegate work];
[timer invalidate];
break; default:
break;
} } @end