一、协议(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;
}