1、委托模式從GoF裝飾(Decorator)模式、適配器(Adapter)模式和模板方法(Template Method)模式等演變而來。不只是Cocoa Touch框架,在Cocoa框架中,委托模式也得到了廣泛的應(yīng)用。
2、委托是為了降低一個(gè)對象的復(fù)雜度和耦合度,使其能夠更具通用性而將其中一些處理置于委托對象中的編碼方式。通用類因?yàn)橥ㄓ眯裕ㄅc具體應(yīng)用的無關(guān)性)而變?yōu)榭蚣茴悾蚣茴惐3治袑ο蟮闹羔槪⒃谔囟〞r(shí)刻向委托對象發(fā)送消息。消息可能只是通知委托對象做一些事情,也可能是對委托對象進(jìn)行控制。

3、舉例說明。
假設(shè)有一個(gè)哲學(xué)家,他要做三件事:“吃飯”、“睡覺”和“工作”。為了提高效率,他會(huì)找一個(gè)徒弟,把事情委托給徒弟做。然后要成為他的徒弟,需要遵守一個(gè)協(xié)議,協(xié)議規(guī)定了要能夠處理好上述三件事。結(jié)合上圖三者關(guān)系如下:

從圖可知,通用類(philosopher)保持指向委托對象(ViewController)的“弱引用”(id<PhilosopherDelegate> delegate),委托對象(ViewController)是哲學(xué)家的“徒弟”,它實(shí)現(xiàn)了協(xié)議PhilosopherDelegate。PhilosopherDelegate規(guī)定了3個(gè)方法:-(void)sleep、-(void)eat和-(void)work方法。
PhilosopherDelegate.h代碼如下:
1 @PRotocol PhilosopherDelegate2 3 @required4 -(void) sleep;5 -(void) eat;6 -(void) work;7 8 @end可以看到,委托協(xié)議philosopherDelegate定義了3個(gè)方法。如果該委托協(xié)議沒有.m文件,它的定義可以放在別的.h文件中。它的實(shí)現(xiàn)類就是委托類ViewController,代碼如下:
1 // 2 //ViewController.h 3 // 4 5 @interface ViewController : UIViewController<PhilosopherDelegate> @end 6 // 7 //ViewController.m 8 // 9 @implementation ViewController10 11 - (void)viewDidLoad12 {13 [super viewDidLoad];14 Philosopher *obj = [[Philosopher alloc ] init];15 obj.delegate = self;16 [obj start];17 }18 19 #pragma -- PhilosopherDelegate方法實(shí)現(xiàn)20 -(void) sleep21 {22 NSLog(@"sleep...");23 }24 25 -(void) eat26 {27 NSLog(@"eat...");28 }29 30 -(void) work31 {32 NSLog(@"work...");33 }34 35 @end委托對象如何與通用類建立引用關(guān)系呢?我們通過viewDidLoad方法中的obj.delegate = self語句來指定委托對象和通用類間的引用關(guān)系。一般情況下,通用類由框架直接提供。在這個(gè)例子中,我們根據(jù)需要自己實(shí)現(xiàn)了通用類Philosopher。Philosopher.h的代碼如下:
1 // 2 //Philosopher.h 3 //DelegatePattern 4 // 5 #import "PhilosopherDelegate.h" 6 @interface Philosopher : NSObject 7 { 8 NSTimer *timer; 9 int count; 10 }11 @property (nonatomic, weak) id<PhilosopherDelegate> delegate;12 -(void) start;13 -(void) handle;14 @end 在上述代碼中,我們定義了delegate屬性,它的類型是id<PhilosopherDelegate>,它可以保存委托對象的引用,其中屬性weak說明是”弱引用“。這里使用弱引用方式是為了防止內(nèi)存引用計(jì)數(shù)增加而導(dǎo)致委托對象無法釋放的問題。Philosopher.m的代碼如下:
1 // 2 //Philosopher.m 3 //DelegatePattern 4 5 #import "Philosopher.h" 6 @implementation Philosopher 7 @synthesize delegate; 8 9 -(void) start10 {11 count= 0;12 timer = [NSTimer scheduledTimerWithTimeInterval:3.013 target:self selector:@selector(handle)userInfo:nil repeats:YES];14 }15 16 -(void)handle17 {18 switch (count)19 {20 case 0:21 [self.delegate sleep];22 count++;23 break;24 case 1:25 [self.delegate eat];26 count++;27 break;28 case 2:29 [self.delegate work];30 [timer invalidate];31 break;32 } 33 }34 @end在本例中,Philosopher模擬一些通用類發(fā)出調(diào)用,這個(gè)調(diào)用通過NSTimer每3秒發(fā)出一個(gè),依次向委托對象發(fā)出消息sleep、eat和work。self.delegate是指向委托對象ViewController的指針,[self.delegate sleep]是調(diào)用ViewController中的sleep方法。
總結(jié)一下它們各自的”職責(zé)“:
1、通用類(哲學(xué)家):保持向委托對象的弱引用, 1 @property (nonatomic, weak) id<PhilosopherDelegate> delegate; ;向委托對象發(fā)送消息 [self.delegate sleep];
2、委托協(xié)議:定義通用類需要實(shí)現(xiàn)的方法 1 -(void) sleep;
3、委托對象(徒弟):實(shí)現(xiàn)/遵守協(xié)議 1 @interface ViewController : UIViewController<PhilosopherDelegate>; ;與通用類建立引用關(guān)系 1 Philosopher *obj = [[Philosopher alloc ] init]; 2 obj.delegate = self; ;實(shí)現(xiàn)協(xié)議方法
1 -(void) sleep2 {3 NSLog(@"sleep...");4 }
資料:《iOS開發(fā)指南》
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注