观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
优点:
1、当两个对象之间松耦合,他们依然可以交互,但是不太清楚彼此的细节。观察者模式提供了一种对象设计,让主题和观察者之间送耦合。主题所知道只是一个具体的观察者列表,每一个具体观察者都符合一个抽象观察者的接口。主题并不认识任何一个具体的观察者,它只知道他们都有一个共同的接口。
2、观察者模式支持“广播通信”。主题会向所有的观察者发出通知。
3、观察者模式符合“开闭原则”的要求。
缺点:
1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进 行循环调用,可能导致系统崩溃。
3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
总结:
观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象。而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
项目地址:https://github.com/GameRisker/Study-Design-Patterns.git
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 |
// // main.m // Observer // // Created by GameRisker on 16/2/7. // Copyright (c) 2016年 GameRisker. All rights reserved. // #import "ConcreteObserver.h" #import "ConcreteSubject.h" #import "Observer.h" #import "Subject.h" #import <Foundation/Foundation.h> int main(int argc, const char *argv[]) { @autoreleasepool { // insert code here... ConcreteSubject *subject = [[ConcreteSubject alloc] init]; [subject Attach:[[ConcreteObserver alloc] initWithName:@"X" concrete:subject]]; [subject Attach:[[ConcreteObserver alloc] initWithName:@"Y" concrete:subject]]; [subject Attach:[[ConcreteObserver alloc] initWithName:@"Z" concrete:subject]]; subject.subjectState = @"ABC"; [subject Notify]; } return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// // Observer.h // // // Created by GameRisker on 16/2/7. // // #import <Foundation/Foundation.h> @protocol Observer <NSObject> - (void)Update; //@end Observer : NSObject @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// // Observer.m // // // Created by GameRisker on 16/2/7. // // #import "Observer.h" @implementation Observer : NSObject - (void)Update { } @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// // ConcreteSubject.h // // // Created by GameRisker on 16/2/7. // // #import "Subject.h" #import <Foundation/Foundation.h> @interface ConcreteSubject : Subject <NSObject> @property(nonatomic, strong) NSString *subjectState; @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// // ConcreteSubject.m // // // Created by GameRisker on 16/2/7. // // #import "ConcreteSubject.h" @implementation ConcreteSubject @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// // Subject.h // // // Created by GameRisker on 16/2/7. // // #import "Observer.h" #import <Foundation/Foundation.h> @interface Subject : NSObject @property(nonatomic, strong) NSMutableArray *m_array; - (void)Attach:(id<Observer>)observer; - (void)Detach:(id<Observer>)observer; - (void)Notify; @end |
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 |
// // Subject.m // // // Created by GameRisker on 16/2/7. // // #import "Subject.h" @implementation Subject - (instancetype)init { if (self = [super init]) { self.m_array = [[NSMutableArray alloc] init]; } return self; } - (void)Attach:(id<Observer>)observer { if (![self.m_array containsObject:observer]) { [self.m_array addObject:observer]; } } - (void)Detach:(id<Observer>)observer { if (![self.m_array containsObject:observer]) { [self.m_array removeObject:observer]; } } - (void)Notify { id<Observer> observer; for (int i = 0; i < [self.m_array count]; i++) { observer = [self.m_array objectAtIndex:i]; [observer Update]; } } @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// // ConcreteObserver.h // // // Created by GameRisker on 16/2/7. // // #import "ConcreteSubject.h" #import "Observer.h" #import <Foundation/Foundation.h> @interface ConcreteObserver : NSObject <Observer> @property(nonatomic, strong) NSString *m_name; @property(nonatomic, strong) NSString *m_observerState; @property(nonatomic, strong) ConcreteSubject *m_subject; - (instancetype)initWithName:(NSString *)name concrete:(ConcreteSubject *)subject; @end |
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 |
// // ConcreteObserver.m // // // Created by GameRisker on 16/2/7. // // #import "ConcreteObserver.h" @implementation ConcreteObserver - (instancetype)initWithName:(NSString *)name concrete:(ConcreteSubject *)subject { if (self = [super init]) { self.m_name = name; self.m_subject = subject; } return self; } - (void)Update { self.m_observerState = self.m_subject.subjectState; NSLog(@"observer : %@ state is %@", self.m_name, self.m_observerState); } @end |