观察者(Obsserver)模式也叫发布/订阅(Publish/Subscribe)模式,是MVC(模式-视图-控制器)模式的重要组成部分。
在软件系统中,一个对象状态的改变可能会连带影响其他很多对象的状态发生改变。观察者模式能够很好的解决这类问题并且最大降低关系类之间的耦合度,给维护、复用和扩展带来很大的方便。
观察者模式有四个角色:
1、抽象主题(Subject)。抽象主题是一个协议,它是一个观察者集合容器,定义了添加观察者方法(attach)、移除观察者方法(detach)和为所有观察者发送通知的方法(notifyObserver)。
2、抽象观察者(Observer)。抽象观察者也是一个协议,它有一个更新方法(update)。
3、具体观察者(ConcreteObserver)。Observer协议的具体实现。
4、具体主题(ConcreteSubject)。Subject协议的具体实现。
下面是抽象主题和抽象观察者:
// // WBSubject.h // DesignPatternsDemo // // Created by 韩学鹏 on 15/6/23. // Copyright (c) 2015年 韩学鹏. All rights reserved. // // 抽象主题 // #import <Foundation/Foundation.h> #import "WBObserver.h" @protocol WBSubject <NSObject> @required /** * 添加观察者 * * @param observer 实现了WBObserver协议的观察者 */ - (void) attach:(id<WBObserver>)observer; /** * 移除观察者 * * @param observer 实现了WBObserver协议的观察者 */ - (void) detach:(id<WBObserver>)observer; /** * 向观察者发送通知 */ - (void) notifyObserver; @end
// // WBObserver.h // DesignPatternsDemo // // Created by 韩学鹏 on 15/6/23. // Copyright (c) 2015年 韩学鹏. All rights reserved. // // 抽象观察者 // #import <Foundation/Foundation.h> @protocol WBObserver <NSObject> @required /** * 观察者的更新方法 */ - (void) update; @end
分别实现了抽象主题和抽象观察者的具体主题和具体观察者:
// // WBConcreteSubject.h // DesignPatternsDemo // // Created by 韩学鹏 on 15/6/23. // Copyright (c) 2015年 韩学鹏. All rights reserved. // // 具体主题 // #import <Foundation/Foundation.h> #import "WBSubject.h" @interface WBConcreteSubject : NSObject <WBSubject> @end // // WBConcreteSubject.m // DesignPatternsDemo // // Created by 韩学鹏 on 15/6/23. // Copyright (c) 2015年 韩学鹏. All rights reserved. // #import "WBConcreteSubject.h" @interface WBConcreteSubject() @property (nonatomic, strong)NSMutableArray *observersArray; //存放添加的观察者的数组 @end @implementation WBConcreteSubject - (id)init { self = [super init]; _observersArray = [NSMutableArray array]; return self; } - (void)attach:(id<WBObserver>)observer { [_observersArray addObject:observer]; } - (void)detach:(id<WBObserver>)observer { if ([_observersArray count]>0) { [_observersArray removeObject:observer]; } } - (void)notifyObserver { NSLog(@"开始发送通知>>>>"); [_observersArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { [obj update]; }]; } @end
// // WBConcreteObserver.h // DesignPatternsDemo // // Created by 韩学鹏 on 15/6/23. // Copyright (c) 2015年 韩学鹏. All rights reserved. // // 具体观察者 // #import <Foundation/Foundation.h> #import "WBObserver.h" @interface WBConcreteObserver : NSObject <WBObserver> + (id)createObserverWithName:(NSString *)name; @end // // WBConcreteObserver.m // DesignPatternsDemo // // Created by 韩学鹏 on 15/6/23. // Copyright (c) 2015年 韩学鹏. All rights reserved. // #import "WBConcreteObserver.h" @interface WBConcreteObserver () { NSString *_myName; } @end @implementation WBConcreteObserver + (id)createObserverWithName:(NSString *)name { WBConcreteObserver *observer = [[WBConcreteObserver alloc] initWithMyName:name]; return observer; } - (id)initWithMyName:(NSString *)name { self = [super init]; _myName = name; return self; } - (void)update { NSLog(@"%@:update...", _myName); } @end
下面是调试代码:
WBConcreteSubject *subject = [[WBConcreteSubject alloc] init]; WBConcreteObserver *observer0 = [WBConcreteObserver createObserverWithName:@"observer0"]; WBConcreteObserver *observer1 = [WBConcreteObserver createObserverWithName:@"observer1"]; WBConcreteObserver *observer2 = [WBConcreteObserver createObserverWithName:@"observer2"]; [subject attach:observer0]; [subject attach:observer1]; [subject attach:observer2]; [subject notifyObserver]; //发送通知 [subject detach:observer1]; //将observer1观察者移除 [subject notifyObserver]; //再次发送通知
输出结果:
2015-06-23 21:05:02.179 DesignPatternsDemo[27387:607] 开始发送通知>>>> 2015-06-23 21:05:02.180 DesignPatternsDemo[27387:607] observer0:update... 2015-06-23 21:05:02.180 DesignPatternsDemo[27387:607] observer1:update... 2015-06-23 21:05:02.181 DesignPatternsDemo[27387:607] observer2:update... 2015-06-23 21:05:02.181 DesignPatternsDemo[27387:607] 开始发送通知>>>> 2015-06-23 21:05:02.182 DesignPatternsDemo[27387:607] observer0:update... 2015-06-23 21:05:02.182 DesignPatternsDemo[27387:607] observer2:update...
最后附上代码文件:观察者模式