黑马程序员--OC-协议与代理设计

 ----------------------ASP.Net+Unity开发.Net培训期待与您交流! ----------------------



一、协议:

  协议是多个类共享一个方法列表.协议中列出的类没有响应的实现,有其他类来实现.

  协议使用指定的名称定义一组相关的方法.这些方法通常有文档说明.所以你知道他们将如何执行.因此如果需要,可以在自己的类中定义他们的实现.

  如果决定实现特定协议的所有方法,也就意味着要遵守这项协议.

  1、基本用途

    (1)可以用来声明一大堆方法(不能声明成员变量)

    (2)只要某个类遵守了这个协议,就相当于拥有这个协议中的所有方法声明

    (3)只要父类遵守了某个协议,就相当于子类也遵守了

      2、协议的编写

       @protocol协议名称

       //方法声明列表

@end

某个类遵守协议

       @interface类名 : 父类<协议名称>

@end

     3、关键字

协议中有2个关键字可以控制方法是否要实现(默认是@required),在大多数情况下,用途在于程序员之间的交流

      @required:这个方法必须要实现(若不实现,编译器会发出警告)

      @optional:这个方法不一定要实现

    4、基协议

   (1)NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它

   (2)其实还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议

   (3)NSObject协议中声明很多最基本的方法,比如description、retain、release等

    (4)建议每个新的协议都要遵守NSObject协议

 5、协议需要关注的地方

    (1)如果你的类采用了NSCopy协议,则必须遵守实现名为copyWithZone的方法.通过在@interface行的一对<>内列出协议名

 (2)可以告诉编译器你正在使用一个协议.这项协议的名称放在类名和它的父类名称之后.

 (3)如果你的类实现了多项协议,协议之间用逗号分开.

 (4)协议不引用任何类型,它是无类的.任何类都可以遵守Drawing协议.

 (5)可以使用ConformsToProtocal:方法检查一个对象是否遵守某项协议.

   例如有一个名为currentObject的对象,并且想要查看它时候是遵循Drawing协议.可以向他放松绘图消息

id currentObjec;

 if([currentObjec : ConformsToProtocal: @protocol(Drawing):== YES]){

  ....//DO SOMETHING;

  }

  这里使用一个专用的@protocol指令用于获取一个协议名称.并产生一个Protocol对象.

 (6)分类也可以采用一项协议 :

  @interface Fraction (Stuff)

  此处Fraction类拥有一个Stuff分类,这个分类采用了NSCopy,NSCoding两个协议. 

  (7)非正式协议:

分正式协议实际上就是一个分类.列出了一组方法,但是并没有实现他们.每个人都继承相同的跟对象,因此非正式分来通常是为跟类定义的.又是非正式协议又叫做抽象协议。声明分正式协议的类并不自己实现这些方法,并且选择实现这些方法的子类需要在他的接口部分重新声明这些方法.同时还要是实现这些方法中的一个或多个,

 二、代理设计模式

   1、设计原理

        A完成一件事,但是自己不能完成,于是他找个代理人B 替他完成这个事情,他们之间便有个协议 (protocol),B继承该协议来完成A代理给他的事情。

   2、设计原则

    (1)首先得拥有某个代理对象属性

    (2)其次要很清楚代理有哪些方法

    (3)最后要保证能解耦

 3、实现方案

    (1)定义一个protocol,在其中声明一些和代理沟通的方法

    (2)拥有一个代理属性id<protocol> delegate

    (3)让代理遵守protocol

 4、实例分析

    下面来举一个实例:妈妈把孩子委托给保姆照顾,于是将需要完成的事情写成一个协议:


协议声明如下:

#import<Foundation/Foundation.h>

@protocolJob <NSObject>

-(void)takeEat;

-(void)takeSleep;

-(void)takePlay;

-(void)takeShower;

@end

 

//声明Nurse类 即代理的人:

#import<Foundation/Foundation.h>

#import"Job.h"

@interfaceNurse : NSObject<Job>//实现该协议

@end

 

//实现文件:

#import"Nurse.h"

@implementationNurse

-(void)takeEat

{

    NSLog(@"小孩饿了,喂它吃饭");

}

-(void)takeSleep

{

    NSLog(@"小孩困了,哄他睡觉");

}

-(void)takePlay

{

    NSLog(@"小孩醒来了,陪他玩");

}

-(void)takeShower

{

    NSLog(@"晚上给小孩洗澡");

}

-(void)dealloc

{

    NSLog(@"Nurse is dealloc");

}

@end

 

//声明一个morther类:

#import<Foundation/Foundation.h>

#import"Job.h"

@classNurse;

@interfaceMorther : NSObject

{

    NSString *name;

    id<Job> delegate;   //此处声明一个代理人,从而mother可以让代理人完成需要代理的事情

}

-(id)initWithName:(NSString*)_name delagat:(id<Job>)_delagete; //传入代理人

@property(nonatomic,copy)NSString*name;

-(void)delagateThings;//被代理的事情

@end

//实现文件

 

#import"Morther.h"

#import"Nurse.h"

@implementationMorther

-(id)initWithName:(NSString*)_name delagat:(id)_delagete

{

    self=[super init];

    if (self) {

        if (name!=_name) {

            [name release];

            name=[_name copy];

            [delegate release];

            delegate=[_delagete retain];

        }

    }

    return self;

}

@synthesizename;

-(void)dealloc

{

    [name release];

    [delegate release];

    NSLog(@"host is dealloc");

}

-(void)delagateThings

{

    int i;

    switch (i) {

        case 1:

            [delegate takeEat];

            break;

        case 2:

            [delegate takePlay];

            break;

        case 3:

            [delegate takeShower];

            break;

        case 4:

            [delegate takeSleep];

            break;

        default:

            break;

    }

    i++;

}

@end

 

//在 main 文件中的实现:

#import<Foundation/Foundation.h>

#import"Morther.h"

#import"Nurse.h"

#import"Job.h"

intmain (int argc, const char * argv[])

{

 

    @autoreleasepool {

       

        NSString *name=[[NSString alloc]initWithFormat:@"小花"];

        Nurse *fengjie=[[Nurse alloc] init];//代理人

        Morther *morther=[[Morther alloc]initWithName:name delagat:fengjie];//这样就将代理人传入mother 对象中,这样morther对象便可以通过nurse来完成她自己不能坐的事情了。

        [name release];

        [NSTimerscheduledTimerWithTimeInterval:2 target:mortherselector:@selector(delagateThings) userInfo:nil repeats:YES];  //调用机制, 2秒调用一次, 调用的对象是morther , 调用的方法是delagateThings;

        [[NSRunLoop currentRunLoop] run];  //让程序一直运行下去,保证上面的调用可以一直进行

        [morther release];

        [fengjie release];   

    }

    return 0;

}

        代理中,需要记住的关键是在发出代理请求的类(A)中声明代理人(B)的实例变量,这样就可以保证A 能通过调用B中B代理的方法来完成B代理的事情,即自己代理给B 的事情。



 ----------------------ASP.Net+Unity开发.Net培训期待与您交流! ----------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值