這篇文章我們就來介紹一下OC中的代理模式,關於代理模式,如果還有同學不太清楚的話,就自己去補充知識了,這里就不做介紹了,這里只介紹OC中是如何實現代理模式的。
這里舉一個簡單的例子:
小孩類,護士類,保姆類,其中小孩類有兩個方法:wash和play
這里代理對象就是:護士類、保姆類,小孩類是被代理對象。
看一下代碼:
首先看一下小孩類:
Children.h
- //
- // Children.h
- // 12_DesignStyle
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- @class Children;//如果沒有這行代碼的話,協議ChildrenDelegate中得Children類型就會查找不到,報錯
- @protocol ChildrenDelegate <NSObject>
- @required
- - (void)wash:(Children *)children;
- - (void)play:(Children *)children;
- @end
- @interface Children : NSObject{
- //Nure *_nure;//保姆
- //這里可以使用多態技術實現,因為保姆,護士有共同的父類NSObject,但是這里不使用這種方式,而是使用id類型
- //但是我們還需要為這個類型添加一些方法,這里就用到了協議
- //這個代理對象必須遵從ChildrenDelegate協議
- id<ChildrenDelegate> _delegate;//這個變量就是小孩的代理對象
- NSInteger timeValue;
- }
- -(void)setDelegate:(id)delegate;
- @end
這里,我們定義了一個協議:ChildrenDelegate,他有兩個必要的方法:wash和play
我們還定義了一個很重要的屬性
_delegate
這個屬性定義有點不一樣,這個就是實現代理對象的精髓所在了,id是不確定類型,所以這個_delegate變量可以被賦值為的類型是:
只要實現了ChildrenDelegate協議的類就可以了。這里就記住了,以后這種定義方法后面會用到很多。相當於Java中的接口類型,只能賦值其實現類的類型。只是這里的定義格式為:id<協議名>
然后就是一個設置協議的方法了,注意參數類型也必須是id的
其實這里面也牽涉到了之前說到的多態特性,所以說代理模式也是建立在多態的特性上的。
Children.m
- //
- // Children.m
- // 12_DesignStyle
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import "Children.h"
- //這里用到了保姆的一些動作
- //假如現在想請一個護士,那么我們又要去從新去請一個護士,那么這里面代碼需要改,把保姆的地方換成護士的地方
- //產生的原因就是因為耦合度太高了,保姆和孩子耦合在一起,如果需要換的話,就需要改動代碼
- //
- @implementation Children
- - (id)init{
- self = [super init];
- if(self != nil){
- [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
- }
- return self;
- }
- -(void)setDelegate:(id)delegate{
- _delegate = delegate;
- }
- - (void)timerAction:(NSTimer *)timer{
- timeValue++;
- if(timeValue == 5){
- [_delegate wash:self];
- }
- if(timeValue == 10){
- [_delegate play:self];
- }
- }
- @end
我們自定義了一個初始化方法,在初始化方法中我們做了一個定時器的工作。
- [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerAction:) userInfo:nil repeats:YES];
這個就是OC中啟動一個簡單的計時器:每隔1s中就去執行一次self中的timerAction方法。
OC中的定時器和java不一樣,他的執行邏輯可以單獨的在一個指定的方法中去做(C中的函數指針差不多,只要傳遞一個函數指針過來,就可以執行指定的函數,所以@selector做的工作就是這個),但是Java中必須實現Runable接口,在run方法中執行指定的邏輯代碼。
在timerAction方法中,我們是判斷當時間到5s了,就執行代理對象的wash方法,10s的時候執行play方法。
在來看一下護士類:
Nure.h
- //
- // Nure.h
- // 12_DesignStyle
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import "Children.h"
- @interface Nure : NSObject<ChildrenDelegate>
- - (void)wash:(Children *)children;
- - (void)play:(Children *)children;
- @end
護士類很簡單,實現ChildrenDelegate協議
Nure.m
- //
- // Nure.m
- // 12_DesignStyle
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import "Nure.h"
- #import "Children.h"
- @implementation Nure
- - (void)wash:(Children *)children{
- NSLog(@"小孩臟了,保姆幫小孩洗澡");
- }
- - (void)play:(Children *)children{
- NSLog(@"小孩哭了,保姆和小孩玩耍");
- }
- @end
在這里就去實現wash和play方法了
在來看一下保姆類:
Nanny.h
- //
- // Nanny.h
- // 12_DesignStyle
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import "Children.h"
- @interface Nanny : NSObject<ChildrenDelegate>
- - (void)wash:(Children *)children;
- - (void)play:(Children *)children;
- @end
Nanny.m
- //
- // Nanny.m
- // 12_DesignStyle
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import "Nanny.h"
- #import "Children.h"
- @implementation Nanny
- - (void)wash:(Children *)children{
- NSLog(@"小孩臟了,護士幫小孩洗澡");
- }
- - (void)play:(Children *)children{
- NSLog(@"小孩哭了,護士和小孩玩耍");
- }
- @end
保姆類和護士類的代碼邏輯是一樣的,因為他們兩個都是實現了一個協議
測試類
main.m
- //
- // main.m
- // 12_DesignStyle
- //
- // Created by jiangwei on 14-10-11.
- // Copyright (c) 2014年 jiangwei. All rights reserved.
- //
- #import <Foundation/Foundation.h>
- #import "Children.h"
- #import "Nure.h"
- #import "Nanny.h"
- //核心:id類型+協議
- //做到低耦合操作
- //同時也可以做到兩個類之間的通信
- int main(int argc, const charchar * argv[]) {
- @autoreleasepool {
- Children *child = [[Children alloc] init];
- Nure *nure = [[Nure alloc] init];
- Nanny *nanny= [[Nanny alloc] init];
- [child setDelegate:nanny];
- // [child setNure:nure];
- [[NSRunLoop currentRunLoop] run];
- }
- return 0;
- }
看到了,測試類很簡單。我們也發現了,代理模式的好處也是顯現出來了,比如現在又來了一個人來照顧孩子:媽媽類,那么我們只要讓媽媽類實現那個協議即可。這種耦合度也不會很高。所以代理模式還是超級有用的,而且我們后面在開發IOS的時候,會發現他里面用到的代理模式很多的。
運行結果:
總結
這一篇就介紹了OC中如何實現代理模式,其實OC中的代理模式核心技術是:id類型+協議+多態