黑马程序员技术交流社区

标题: OC学习之协议与代理模式 [打印本页]

作者: 世年单    时间: 2016-1-18 13:57
标题: OC学习之协议与代理模式
这里举一个简单的例子:
小孩类,护士类,保姆类,其中小孩类有两个方法:wash和play,这里代理对象就是:护士类、保姆类,小孩类是被代理对象。
看一下代码:
首先看一下小孩类:
Children.h
#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
#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];  

Nure.h
护士类:
#import <Foundation/Foundation.h>  
#import "Children.h"  
@interface Nure : NSObject<ChildrenDelegate>  
- (void)wash:(Children *)children;  
- (void)play:(Children *)children;  
@end  

Nure.m
协议:
#import "Nure.h"  
#import "Children.h"   
@implementation Nure   
- (void)wash:(Children *)children{  
    NSLog(@"小孩脏了,保姆帮小孩洗澡");  
}   
- (void)play:(Children *)children{  
    NSLog(@"小孩哭了,保姆和小孩玩耍");  
}   
@end  

Nanny.h
保姆类:
#import <Foundation/Foundation.h>  
#import "Children.h"  
@interface Nanny : NSObject<ChildrenDelegate>  
- (void)wash:(Children *)children;  
- (void)play:(Children *)children;  
@end  

Nanny.m

#import "Nanny.h"  

#import "Children.h"  
@implementation Nanny  
- (void)wash:(Children *)children{  
    NSLog(@"小孩脏了,护士帮小孩洗澡");  
}  
- (void)play:(Children *)children{  
    NSLog(@"小孩哭了,护士和小孩玩耍");  
}  
@end

main.m
#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;  
}  

总结
这一篇就介绍了OC中如何实现代理模式,其实OC中的代理模式核心技术是:id类型+协议+多态




作者: foolishlovepig    时间: 2016-1-18 19:17
好厉害,总结的很棒
作者: toveyloves    时间: 2016-1-19 01:32
每份协议你传了参数却不使用,这是为什么呢?




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2