每天进步一点点文集小岛語錄集

[设计模式]06.观察者模式

2019-11-15  本文已影响0人  沈枫_ShenF

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。

观察者模式UML

从UML图可以看到,观察者模式有两大类:主题和观察者,有以下四个角色:
(1)Subject:抽象主题,他把所有观察者对象保存在一个集合里,可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
(2)ConcreteSubject:具体主题,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知
(3)Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
(4)ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。

举例说明

案例:订阅书刊。

1.定义接口

@protocol SubjectProtocol <NSObject>
- (NSString*)test;
- (void)subMessage:(id)message withSubNumber:(NSString *)withSubNumber;
@end

2.主题

@interface SubjectCenter : NSObject
// 创建书刊订阅号
+ (void)creatNumber:(NSString *)subNumber;

// 移除订阅号
+ (void)removeNumber:(NSString *)subNumber;

// 添加用户
+ (void)addUser:(id <SubjectProtocol>)user wihtNumber:(NSString *)userNumber;

// 移除用户
+ (void)removeUser:(id <SubjectProtocol>)user withNumber:(NSString *)userNumber;

// 发送消息
+ (void)sendMessage:(id)message withSubNumber:(NSString *)SubNumber;

实现中,使用NSHashTable来保存使用者,NSHashTable 就是一个集合,但是它是弱引用的。

#import "SubjectCenter.h"
static NSMutableDictionary *bookCenter = nil;
@implementation SubjectCenter

+ (void)initialize {
    if (self == [SubjectCenter class]) {
        bookCenter = [NSMutableDictionary dictionary];
    }
}

// 创建书刊订阅号
+ (void)creatNumber:(NSString *)subNumber {
    NSHashTable *hashTable = [self existNumber:subNumber];
    if (hashTable == nil) {
        hashTable = [NSHashTable weakObjectsHashTable];
        [bookCenter setObject:hashTable forKey:subNumber];
    }
}

// 移除订阅号
+ (void)removeNumber:(NSString *)subNumber {
    NSHashTable *hashTable = [self existNumber:subNumber];
    if (hashTable) {
        [bookCenter removeObjectForKey:subNumber];
    }
}

// 添加用户
+ (void)addUser:(id <SubjectProtocol>)user wihtNumber:(NSString *)userNumber {
    NSHashTable *hashTable = [self existNumber:userNumber];
    [hashTable addObject:user];
}

// 移除用户
+ (void)removeUser:(id <SubjectProtocol>)user withNumber:(NSString *)userNumber {
    NSHashTable *hashTable = [self existNumber:userNumber];
    [hashTable removeObject:user];
}

// 发送消息
+ (void)sendMessage:(id)message withSubNumber:(NSString *)SubNumber {
    NSHashTable *hashTable = [self existNumber:SubNumber];
    if (hashTable) {
        NSEnumerator *enumerato = [hashTable objectEnumerator];
        id <SubjectProtocol> object = nil;
        while (object = [enumerato nextObject]) {
            if ([object respondsToSelector:@selector(subMessage:withSubNumber:)]) {
                [object subMessage:message withSubNumber:SubNumber];
            }
        }
    }
}

// 实现了代理方法
+ (NSHashTable *)existNumber:(NSString *)subStringNumber {
    return [bookCenter objectForKey:subStringNumber];
}
@end

3.观察者观察

@interface ViewController () <SubjectProtocol>
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 创建订阅
    [SubjectCenter creatNumber:@"string"];
    // 添加订阅
    [SubjectCenter addUser:self wihtNumber:@"string"];
    // 发送消息
    [SubjectCenter sendMessage:@"11" withSubNumber:@"string"];
}

- (void)subMessage:(id)message withSubNumber:(NSString *)withSubNumber {
    NSLog(@"----%@----%@",message, withSubNumber);
}
@end

load和initialize方法详见这篇文章

KVO就是一种观察者模式的设计

KVO的底层实现原理请看这篇文章

上一篇 下一篇

猜你喜欢

热点阅读