设计模式
设计模式是用来解决编程某些特定问题。
单例模式
什么时候使用单例模式?
在一个工程中,有一些类只需要一个实例变量,我们就可以将这些类设计成单例模式
单例模式的作用?
当一个类A
被设计成单例模式时,由A
构造出的实例对象之于其它类来讲为全局实例对象,即在每一个类中由A
构造出的实例对象,都为相同对象
在OC中如何将一个类设计成单例模式?
在要被设计成单例的类的.h文件中声明一个构造单例方法,如:
+(Student *)shareIntance;
实现该方法
static Student *st = nil;//声明一个静态实例对象 +(Student *)shareIntance{ if (st == nil) { st = [[Student alloc] init]; } return st; } //为了防止通过 alloc 或 new 创建新的实例 +(id)allocWithZone:(struct _NSZone *)zone{ @synchronized(self){ if (st == nil) { st = [[super allocWithZone:zone] init]; } } return st; } //为了防止copy产生出新的对象,需要实现 NSCopying 协议 -(id)copyWithZone:(NSZone *)zone{ return self; }
观察者模式
什么是观察者模式?
在工程中,一些类去观察A类
,当A类
发生变化时,这些观察类就会收到消息,做出相应反应。
什么时候使用观察者模式?
当一个类需要发送消息给多个类的时候,就用观察者模式
观察者模式的作用?
一对多的发送消息
如何在OC中实现观察者模式?
OC中观察者模式的设计基础:KVC / KVO
KVC的由来:在iOS2.0之前,并没有属性来访问类中实例变量,那时候开发人员使用 键值编码
的方式来访问类中的实例变量,即 KVC
方式。
使用KVC来访问类中实例变量:
Student *st = [[Student alloc] init];
//赋值
[st setValue:@"vincent" forKey:@"_name"];
[st setValue:@25 forKey:@"_age"];
//访问
NSString *name = [st valueForKey:@"_name"];
NSNumber *age = [st valueForKey:@"_age"];
//键路径编码
Book *book = [Book new];
//st.book = book;
//st.book.bookName = @"金品梅";
[st setValue:book forKeyPath:@"_book"];
[st setValue:@"金品梅" forKeyPath:@"_book._bookName"];
NSLog(@"%@",[book description]);
NSString *bookName = [st valueForKeyPath:@"_book._bookName"];
[st setValue:@"guangzhou" forKeyPath:@"_address"];
NSLog(@"des = %@",[st description]);
KVO的由来:在编程过程中,我们经常需要判断目标是否发生改变,以便及时的做出对应的处理。此时苹果公司就提供一种策略,即OC运行时
提供了kVO
技术。其中KVO
是基于KVC
实现。
KVO的实现:
1. 注册成为观察者
2. 观察者定义KVO回调
3. 移除观察者
代码示例:
-(id)initWithStudent:(Student *)st{
if (self = [super init]) {
self.st = st;
//1.注册观察者
[self.st addObserver:self forKeyPath:@"_name" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:nil];
[self.st addObserver:self forKeyPath:@"_age" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:nil];
[self.st addObserver:self forKeyPath:@"_book._bookName" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:nil];
}
return self;
}
//注册KVO回调
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if ([keyPath isEqualToString:@"_name"]) {
NSLog(@"name change = %@",change);
}
if ([keyPath isEqualToString:@"_age"]) {
NSLog(@"age change = %@",change);
}
if ([keyPath isEqualToString:@"_book._bookName"]) {
NSLog(@"book change = %@",change);
}
}
//移除观察者
-(void)dealloc{
[self.st removeObserver:self forKeyPath:@"_name" context:nil];
[self.st removeObserver:self forKeyPath:@"_age" context:nil];
[self.st removeObserver:self forKeyPath:@"_book._bookName" context:nil];
}
通知
通过学习KVO
,我们发现KVO
是一种简单的观察者设计模式,涉及到两个对象,分别是观察者和被观察者。这种方式实质有很大局限性,那么OC的Foundation
框架,在基于KVO
的基础上又为开发者提供了新的一种观察者设计模式,即通知
。
通知是一种发送给一个或者多个观察者,用来通知其在程序中发生了某个事件的消息。它是一种程序中事件的发起者或者是处理者和其它想要知道该事件的对象的沟通的一种方式。消息的接受者,即观察响应改事件来变换自己的UI、行为或者状态。
在OC中,使用NSNotification
类来表示一个通知。
//初始化一个NSNotification类的实例对象
NSNotification *notification1 = [NSNotification notificationWithName:@"通知名称" object:self];
NSNotification *notification2 = [NSNotification notificationWithName:@"通知名称" object:self userInfo:@{@"content":@"jay is on living"}];
其中:
- name:表示通知名称,最好英文名,用来识别通知对象
- object:表示通知的发起人
userInfo:表示通知的内容
——————————————————————————
在现实生活中,我们的邮件都需要由邮局发送给接收人。在OC中也一样,Foundation
框架定义了一个单例类,通知中心NSNotificationCenter
来统一发送通知的实例对象给观察者
//通知中心 单例类,拿到通知中心的单例
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
//通知中心发送通知
[center postNotification:notification1];
简便写法,通知中心直接发送通知
[center postNotificationName:<#(NSString *)#> object:<#(id)#>]
[center postNotificationName:<#(NSString )#> object:<#(id)#> userInfo:<#(NSDictionary )#>]
建立通知发送机制,步骤如下:
- 注册相关监听者,并实现监听收到通知时的方法
- 在需要的时候,被监听的对象去通知中心发送通知
- 在
delloc
方法中,移除通知
关键代码示例:
//到通知中心去让自己成为某个通知的监听对象
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationAction:) name:TeacherWithStudentNotification object:nil];
//实现当前对象接收通知时的方法
-(void)notificationAction:(NSNotification *)notification{
NSLog(@"notification userinfo = %@",notification.userInfo);
NSLog(@"上厕所");
}
//到main函数调用此方法,发送通知
-(void)sendNoficaiton{
[[NSNotificationCenter defaultCenter] postNotificationName:TeacherWithStudentNotification object:self userInfo:@{@"context":@"下课"}];
}
//在delloc方法中移除通知
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:TeacherWithStudentNotification object:nil];
}