OC协议,代理模式与单例模式

一、协议(protocol)

1、协议的基本用途

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

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

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

2、协议的格式

(1)协议的编写

协议中的方法总是声明在@protocol和@恩典中,例如

@protocol 协议名称
// 方法声明列表
@end<

(2)某个类遵守协议

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

@end

3、关键字

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

@required:若在方法前做此声明,则@required后面的所有方法必须要实现,直到有方法声明了@optional(默认的声明)。

@optional:若在方法前做此声明,则@optional后面的所有方法不一定要实现,直到另一个方法声明了@required。

4、协议遵守协议

(1)一个协议可以遵守其他多个协议,多个协议之间用逗号“ ,” 隔开。

(2)一个协议遵守了其他协议,就相当于拥有了其他协议中的方法声明。

例如:

@protocol 协议名称 <协议1,协议2>

@end

5、基协议

(1)NSObject是一个基类,最根本最基本的类,任何其他类最终都要继承它,然而还有一个协议,名字也叫NSObject,它是一个基协议,最根本最基本的协议。

(2)NSObject协议中声明很多最基本的方法,比如description、retain、release等,由此也可知基类NSObject遵守基协议NSObject

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

6、定义变量时指定协议

// NSObject类型的对象,并且要遵守NSCopying协议
NSObject<NSCopying> *obj;
// 任何OC对象,并且要遵守NSCoding协议
id<NSCoding> obj2;


代码示例:

<strong>/**协议1*/</strong>
#import <Foundation/Foundation.h>

@protocol Protocol1 <NSObject>
//必须实现
@required
- (void)test1;
- (void)test2;
//不一定要实现,可选
@optional
- (void)test3;
@end

<strong>/**协议3*/</strong>
#import <Foundation/Foundation.h>

@protocol Protocol3 <NSObject>
@end


<strong>/**协议2,且遵守协议1*/</strong>
#import <Foundation/Foundation.h>
@protocol Protocol1;
@protocol Protocol2 <Protocol1>
- (void)test4;
- (void)test5;
@end

<strong>/**Dog类,且遵守协议2*/</strong>
#import <Foundation/Foundation.h>
//声明有protocol2这个协议
@protocol Protocol2;
@interface Dog : NSObject <Protocol2>
@end

#import "Dog.h"
#import "Protocol2.h"

@implementation Dog
- (void)test5
{
    
}
- (void)test4
{
    
}
@end


<strong>/**Person类,且遵守协议1,定义了一个遵守协议3的变量*/</strong>

#import <Foundation/Foundation.h>
//声明有Protocol1这个协议
@protocol Protocol1;
@protocol Protocol3;
@class Dog;
@interface Person : NSObject <Protocol1>
//定义了一个需要遵守协议的成员变量
@property (nonatomic,strong) Dog<Protocol3> *dog;
@end

#import "Person.h"
#import "Protocol1.h"
@implementation Person
- (void)test1
{
    
}
- (void)test2
{
    
}
@end


<strong>/**Student类,继承自Person类,相当与Student类也遵守协议1,Student.h文件中定义了协议5,Student类遵守该协议*/</strong>

#import "Person.h"

@protocol Protocol5 <NSObject>
- (void)test7;
@end

@interface Student : Person <Protocol5>

@end

#import "Student.h"

@implementation Student
- (void)test7
{
    
}
@end

<strong>
/**main.m文件*/</strong>

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
#import "Protocol1.h"
#import "Protocol2.h"
#import "Protocol3.h"
#import "Student.h"

int main()
{
    NSObject *object = [[Person alloc] init];

    // 要求接收的对象必须继承自Person且遵守Protocol1协议
    Person<Protocol1> *p = [[Person alloc] init];
    

    // 要求NSObject类型的对象遵守Protocol2
    NSObject<Protocol2> *obj2 = [[Dog alloc] init];
 
    //  任何遵守协议2的OC对象  
    id<Protocol2> obj3 = [[Dog alloc] init];
    
    //obj3遵守协议2,而Person中的实例变量dog要求遵守协议3,所以会报错
    //p.dog = obj3;
    //报错: Assigning to 'Dog<Protocol3> *' from incompatible type '__strong id<Protocol2>'

    // Person类遵守了协议1,所以Student也遵守协议1
    id<Protocol1> obj4 = [[Student alloc] init];
    
    return 0;
}


二、代理模式

1、设计原理

对象之间经常需要互相通信,而通信方式有很多种,其中Delegate pattern(代理模式)的编程设计模式被广泛采用。该模式的主旨是:定义一套协议,某对象若想成为另一个对象的代理,则需遵循此协议,以便成为其代理对象。而另一个对象则可以给其代理对象回传一些信息,也可以在发生相关事件时通知代理对象。

2、设计原则

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

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

(3)最后要保证能解耦(例如数据与业务逻辑解耦)

3、实现方案

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

(2)拥有一个代理属性id<protocol>delegate(声明为id类型,以便接受任何OC对象)

(3)让代理遵守protocol

代码实例:

/**
 *模拟代理模式:买票人想知道电影票的信息,但又不想亲自去电影院查询,于是委托别人去查票价和剩余票数并将结果返回给委  *托人,由此产生一个代理过程
 */

/**代理协议 TicketDelegate*/</strong>

#import <Foundation/Foundation.h>

@protocol TicketDelegate <NSObject>
// 返回剩票数
- (int)TicketNumber;
// 返回票价
- (double)TicketPrice;
@end


<strong>/**代理对象 Agent,遵守TicketDelegate协议*/</strong>

#import <Foundation/Foundation.h>
#import "Person.h"
@protocol TicketDelegate;
@interface Agent : NSObject <TicketDelegate>

@end


#import "Agent.h"
#import "TicketDelegate.h"
@implementation Agent
// 代理对象去查询剩票
- (int)TicketNumber
{
    return 10;
}

// 代理对象去查询票价
- (double)TicketPrice
{
    return 500;
}
@end



<strong>/**Person类*/</strong>

#import <Foundation/Foundation.h>
@protocol TicketDelegate;
@interface Person : NSObject
//代理对象
@property (nonatomic,retain) id<TicketDelegate> agent;
- (void)buyTicket;
@end



#import "Person.h"
#import "TicketDelegate.h"
@implementation Person

// 代理对象去查询票价和剩票并返回结果的过程
- (void)buyTicket
{
    int number = [_agent TicketNumber];
    double price = [_agent TicketPrice];
    NSLog(@"number=%d,price=%f",number,price);
    
}

- (void)dealloc
{
    [_agent release];
    [super dealloc];
}
@end


<strong>/**main.m文件*/</strong>
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Agent.h"
#import "TicketDelegate.h"
int main()
{
    //  买票人
    Person *p = [[Person alloc] init];
    
    // 代理对象
    Agent *a = [[Agent alloc] init];
    
    // 买票人委托对象去查询票价和剩票数
    p.agent = a;
    
    // 代理对象返回结果
    [p buyTicket];
    
    
    [a release];
    [p release];
    
    return 0;
}


程序的运行结果如下



三、单例模式

1、什么是单例模式

单例是在程序声明周期里有且仅有被实例化过一次。单例模式主要应用于资源共享控制。

2、设计原则

(1)实现一个静态实例,将其设置为nil

(2)实现一个构造方法用于获取该实例(通常将该方法命名为sharedInstance或者是sharedManager)

(3)重写allocWithZone方法,保证试图通过alloc,init和allocWithZone手段获取一个新实例时不会产生一个新实例

代码示例:

/**Singleton,单例类*/
#import <Foundation/Foundation.h>

@interface Singleton : NSObject

+ (Singleton *)sharedInstanceMethod;

@end

#import "Singleton.h"

// 静态变量在程序运行之前创建,在程序的整个运行期间始终存在,直到程序结束
static Singleton *sharedInstance = nil;

@implementation Singleton

+ (Singleton *)sharedInstanceMethod
{
    // 加入线程安全,保证只在一个线程中创建,防止多线程创建多个实例
    @synchronized(self)
    {
        if (sharedInstance == nil)
        {
            sharedInstance = [[self alloc] init];
        }
    }
    
    
    return sharedInstance;
}

/* 
 使用alloc方法初始化一个类的实例时,默认时调用了allocWithZone方法,为了保证单例,所以需要覆盖该方法
 NSZone:用来分配和释放内存的一种方式,它不是一个对象,而是用c结构存储了关于对象的内存管理信息
*/

// 只有一次alloc单例,其他alloc方法都返回nil
+(id)allocWithZone:(struct _NSZone *)zone
{
    @synchronized(self)
    {
        if (sharedInstance == nil) {
            // 调用allocWithZone:zone创建一个新实例
	    sharedInstance = [super allocWithZone:zone];

            

        }
    }
    
    return sharedInstance;
}
@end


/**maim.m文件*/

#import <Foundation/Foundation.h>
#import "Singleton.h"
#import "Person.h"
int main()
{
    
    Singleton *s = [Singleton sharedInstanceMethod];
    NSLog(@"%@",s);
    
    Singleton *s1 = [Singleton sharedInstanceMethod];
    NSLog(@"%@",s1);
    
    Singleton *s2 = [[Singleton alloc] init];
    NSLog(@"%@",s2);
   
    
    return 0;
}



程序的运行结果如下:







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值