这次来介绍一下观察者模式,这种模式可以说使用的是最多的,也最常见。我们现在使用的智能手机的应用在本质上也都是观察者模式的一种体现,这些手机应用都是事件驱动机制,只要有事件发生,就会做出一系列的响应处理,在没有事件的时候,什么也不会发生。这就是观察者模式,观察者模式需要一个被观察者,和一个或者多个观察者。当被观察者的状态发生改变时,观察者会做出相应的处理。
观察者模式定义
观察者模式(Observer Pattern)也叫做发布订阅模式(Publish/subscribe)。
Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.(定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于他的对象都会得到通知并被自动更新。)
观察者模式类图
观察者模式说明
Subject被观察者
定义被观察者必须实现的职责,它必须能够动态的增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。
Observer观察者
观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。
ConcreteSubject具体的被观察者
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
ConcreteObserver具体的观察者
每个观察者在接收到消息后的处理反应应是不同的,各个观察者有自己的处理逻辑。
观察者模式的优点
观察者和被观察者之间是抽象耦合
建立一套触法机制
观察者模式的缺点
观察者模式需要考虑开发效率和运行效率的问题。
观察者模式在iOS中的应用
观察者模式在iOS中的应用我知道主要有两个,一个是消息中心(NSNotificitonCenter
),他并不是严格意义上的观察者模式,但是很类似,首先将观察者注册到消息中心,被观察者可以向消息中心发送消息通知给观察者,从而产生相应的逻辑。再有一个就是Cocoa
的KVO
机制,也就是Key Value Observer
,他可以检测一个对象的某一个属性,当他发生改变时,观察者自动的去调用相应的方法。
下面附上一个用objective-C
写的类似的一个观察者模式的小程序:
Student
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@interface Student : NSObject
@property ( copy , nonatomic ) NSString * name ;
@property ( copy , nonatomic ) NSString * Ttel ;
- ( id ) initWithName: ( NSString * ) aName ;
- ( void ) updatePhone: ( NSString * ) aTel ;
@end
@implementation Student
@synthesize name = _name ;
@synthesize Ttel = _Ttel ;
- ( id ) initWithName: ( NSString * ) aName
{
if ( self = [ super init ]) {
_name = aName ;
}
return self ;
}
- ( void ) updatePhone: ( NSString * ) aTel
{
self . Ttel = aTel ;
}
@end
Teacher
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
@interface Teacher : NSObject
@property ( copy , nonatomic ) NSString * tel ;
@property ( copy , nonatomic ) NSString * name ;
@property ( strong , nonatomic ) NSMutableArray * observers ;
- ( id ) initWtihName: ( NSString * ) aName andTel: ( NSString * ) aTel ;
- ( void ) addObserver: ( NSObject * ) aObserver ;
- ( void ) removeObserver: ( NSObject * ) aObserver ;
- ( void ) noticeObservers ;
@end
#import "Student.h"
@implementation Teacher
@synthesize name = _name ;
@synthesize tel = _tel ;
@synthesize observers = _observers ;
- ( id ) initWtihName: ( NSString * ) aName andTel: ( NSString * ) aTel
{
if ( self = [ super init ]) {
_name = aName ;
_tel = aTel ;
_observers = [[ NSMutableArray alloc ] init ];
}
return self ;
}
- ( void ) addObserver: ( NSObject * ) aObserver
{
[ _observers addObject: aObserver ];
}
- ( void ) removeObserver: ( NSObject * ) aObserver
{
[ _observers removeObject: aObserver ];
}
- ( void ) noticeObservers
{
[ self . observers enumerateObjectsUsingBlock: ^ ( id obj , NSUInteger idx , BOOL * stop ) {
if ([ obj respondsToSelector: @selector ( updatePhone: )]) {
[ obj updatePhone: _tel ];
}
}];
}
@end
main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#import "Student.h"
#import "Teacher.h"
int main ( int argc , const char * argv [])
{
@autoreleasepool {
// insert code here...
Teacher * t = [[ Teacher alloc ] initWtihName : @"teacher" andTel : @"123456" ];
Student * s1 = [[ Student alloc ] initWithName : @"Student1" ];
Student * s2 = [[ Student alloc ] initWithName : @"Student2" ];
[ t addObserver : s1 ];
[ t addObserver : s2 ];
NSLog ( @"%@ %@" , s1 . Ttel , s2 . Ttel );
t . tel = @"654321" ;
[ t noticeObservers ];
NSLog ( @"%@ %@" , s1 . Ttel , s2 . Ttel );
}
return 0 ;
}
例子很简单就是老师将电话号码留给同学们,当老师电话号码改变时,同学们自动的也会将老师的电话号码改变。其实写的并不好,最好还是定义两个Protocol
,一个是Observer
一个是Subject
,然后老师和学生分别遵循Observer
和Subject
协议,这样的话就比较好了。