iOS设计模式 - 观察者

原理图

说明

1. cocoa框架本身实现了观察者模式(通知中心以及KVO)

2. 本人所写的例子,实现了通知中心,其特殊的地方在于,不用移除订阅了通知的对象

源码

https://github.com/YouXianMing/ObserverPattern

//
//  SubscriptionServiceCenter.h
//  ObserverPattern
//
//  Created by YouXianMing on 15/7/29.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SubscriptionServiceCenterProtocol.h"

/**
 *  订阅服务中心(实现了系统的通知中心业务逻辑)
 *
 *  = 注意 = 没有考虑发送通知的时候,同步与异步的问题
 *
 */
@interface SubscriptionServiceCenter : NSObject

/**
 *  创建订阅号
 *
 *  @param subscriptionNumber 订阅号码
 */
+ (void)createSubscriptionNumber:(NSString *)subscriptionNumber;

/**
 *  移除订阅号(参与到该订阅号码的所有客户不会再收到订阅信息)
 *
 *  @param subscriptionNumber 订阅号码
 */
+ (void)removeSubscriptionNumber:(NSString *)subscriptionNumber;

/**
 *  将指定客户从指定订阅号上移除掉
 *
 *  @param customer           客户对象
 *  @param subscriptionNumber 订阅号码
 */
+ (void)removeCustomer:(id <SubscriptionServiceCenterProtocol>)customer fromSubscriptionNumber:(NSString *)subscriptionNumber;

/**
 *  通知签订了订阅号码的对象
 *
 *  @param message            信息对象
 *  @param subscriptionNumber 订阅号码
 */
+ (void)sendMessage:(id)message toSubscriptionNumber:(NSString *)subscriptionNumber;

/**
 *  客户订阅指定的订阅号
 *
 *  @param customer           客户对象
 *  @param subscriptionNumber 订阅号码
 */
+ (void)addCustomer:(id <SubscriptionServiceCenterProtocol>)customer withSubscriptionNumber:(NSString *)subscriptionNumber;

@end
//
//  SubscriptionServiceCenter.m
//  ObserverPattern
//
//  Created by YouXianMing on 15/7/29.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import "SubscriptionServiceCenter.h"

static  NSMutableDictionary  *_subscriptionNumberDictionary = nil;

@implementation SubscriptionServiceCenter

#pragma mark - 初始化
+ (void)initialize {

    if (self == [SubscriptionServiceCenter class]) {

        _subscriptionNumberDictionary = [NSMutableDictionary dictionary];
    }
}

+ (void)createSubscriptionNumber:(NSString *)subscriptionNumber {

    NSParameterAssert(subscriptionNumber);

    NSHashTable *hashTable = [self existSubscriptionNumber:subscriptionNumber];

    if (hashTable == nil) {

        hashTable = [NSHashTable weakObjectsHashTable];
        [_subscriptionNumberDictionary setObject:hashTable forKey:subscriptionNumber];
    }
}

+ (void)removeSubscriptionNumber:(NSString *)subscriptionNumber {

    NSParameterAssert(subscriptionNumber);

    if ([self existSubscriptionNumber:subscriptionNumber]) {

        [_subscriptionNumberDictionary removeObjectForKey:subscriptionNumber];
    }
}

+ (void)removeCustomer:(id <SubscriptionServiceCenterProtocol>)customer fromSubscriptionNumber:(NSString *)subscriptionNumber {

    NSParameterAssert(subscriptionNumber);

    NSHashTable *hashTable = [self existSubscriptionNumber:subscriptionNumber];

    if (hashTable && customer) {
        [hashTable removeObject:customer];
    }
}

+ (void)sendMessage:(id)message toSubscriptionNumber:(NSString *)subscriptionNumber {

    NSParameterAssert(subscriptionNumber);

    NSHashTable *hashTable = [self existSubscriptionNumber:subscriptionNumber];

    if (hashTable) {

        NSEnumerator *enumerator = [hashTable objectEnumerator];

        id <SubscriptionServiceCenterProtocol> customer = nil;
        while (customer = [enumerator nextObject]) {

            if ([customer respondsToSelector:@selector(subscriptionMessage:subscriptionNumber:)]) {
                [customer subscriptionMessage:message subscriptionNumber:subscriptionNumber];
            }
        }
    }
}

+ (void)addCustomer:(id)customer withSubscriptionNumber:(NSString *)subscriptionNumber {

    NSParameterAssert(customer);
    NSParameterAssert(subscriptionNumber);

    NSHashTable *hashTable = [self existSubscriptionNumber:subscriptionNumber];
    [hashTable addObject:customer];
}

#pragma mark - 私有方法
+ (NSHashTable *)existSubscriptionNumber:(NSString *)subscriptionNumber {

    return [_subscriptionNumberDictionary objectForKey:subscriptionNumber];
}

@end
//
//  SubscriptionServiceCenterProtocol.h
//  ObserverPattern
//
//  Created by YouXianMing on 15/7/29.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import <Foundation/Foundation.h>

@protocol SubscriptionServiceCenterProtocol <NSObject>

/**
 *  接收到的订阅信息
 *
 *  @param message            订阅信息
 *  @param subscriptionNumber 订阅编号
 */
- (void)subscriptionMessage:(id)message subscriptionNumber:(NSString *)subscriptionNumber;

@end

分析

让一个对象,遵循某种制定的协议(接口)来完成特定的功能,是cocoa开发中很重要的一种技巧

订阅以及针对订阅号发布信息的完整流程

时间: 2024-12-20 23:06:30

iOS设计模式 - 观察者的相关文章

IOS设计模式之四(备忘录模式,命令模式)

本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq)翻译,如果你发现有什么错误,请与我联系谢谢. 备忘录(Memento)模式 备忘录模式快照对象的内部状态并将其保存到外部.换句话说,它将状态保存到某处,过会你可以不破坏封装的情况下恢复对象的状态,也就是说原来对象中的私有数据仍然是私有的. 如何使用备忘录模式 在ViewController.m中增加

IOS设计模式之三(适配器模式,观察者模式)

本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq)翻译,如果你发现有什么错误,请与我联系谢谢. 适配器(Adapter)模式 适配器可以让一些接口不兼容的类一起工作.它包装一个对象然后暴漏一个标准的交互接口. 如果你熟悉适配器设计模式,苹果通过一个稍微不同的方式来实现它-苹果使用了协议的方式来实现.你可能已经熟悉UITableViewDelegat

IOS设计模式之一(MVC模式,单例模式)

本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq)翻译,如果你发现有什么翻译错误,请与我联系谢谢. iOS 设计模式-你可能已经听说过这个词,但是你真正理解它意味着什么吗?虽然大多数的开发者可能都会认为设计模式是非常重要的,然而关于设计模式这一主题的文章却不多,并且有时候我们开发者在写代码的时候也不会太关注它. 在软件设计领域,设计模式是对通用问题

iOS设计模式

iOS设计模式,很多开发这都是听得多,但是有时候自己即使用过也不会很在意,开发者在写代码的时候也不会注意它. 在软件设计领域,设计模式是对通过问题的可复用的解决方案.设计模式是一系列帮你写出可理解和复用的模板,设计模式帮你创建松耦合的代码,你不需要花费太多就可以改变或者替换代码中的组件. (1)代理模式 应用场景:当一个类的某些功能需要由其他别的类别来实现的,但是又不确定是哪个类 优势:松耦合 实例:tableView的数据源delegate,通过和protocol的配合,完成委托. 列表row

iOS 设计模式

Ios 设计模式,你可能听说过,但是你真正知道这是什么意思么?大部分的开发者大概都同意设计模式很重要,但是关于这一部分却没有很多的文章去介绍它,我们开发者很多时候写代码的时候也并不重视设计模式. 设计模式是在软件设计上去解决普通问题的可重用的方法.他们是是帮助你让所写的代码更加容易理解和提高可重用性的模板.它们还可以帮你创建松散耦合的代码是你能不费很大功夫就可以改变或者替代你的代码中的一部分. 如果你对设计模式感到生疏,那么我有个好消息告诉你!首先,你已经用了很多ios设计模式多亏了Cocoa

IOS设计模式之二(门面模式,装饰器模式)

本文原文请见:http://www.raywenderlich.com/46988/ios-design-patterns. 由 @krq_tiger(http://weibo.com/xmuzyq)翻译,如果你发现有什么错误,请与我联系谢谢. 门面(Facade)模式(译者注:facade有些书籍译为门面,有些书籍译为外观,此处译为门面) 门面模式针对复杂的子系统提供了单一的接口,不需要暴漏一些列的类和API给用户,你仅仅暴漏一个简单统一的API. 下面的图解释了这个概念: 这个API的使用者

iOS 通知观察者的被调函数不一定运行在主线程

Tony in iOS | 08/08/2013 iOS 通知观察者的被调函数不一定运行在主线程 今天修复Bug时候发现的一个小细节,记录下. 问题描述 事情是这样的:我在A视图(UITableView)注册了一个通知,当接收到此通知时,就重新读取数据并调用[tableView reloadData].但是视图有时刷新后的显示的内容不对,再重新切换下视图又正常了. 代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 //A视图在初始化时注册通知 - (voi

iOS设计模式(代码分析系列2:简单工厂模式)

简单工厂模式示例代码下载地址, 1.简述 首先需要说明一下,简单工厂模式不属于23种GOF设计模式之一.它也称作静态工作方法模式,是工厂方法模式的特殊实现(也就是说工厂模式包含简单工厂模式).这里对简单工厂模式进行介绍,是为后面的工厂方法和抽象工厂模式做一个引子. 2.定义 "专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类." 世界上就是由一个工厂类,根据传入的参数,动态地决定创建出哪一个产品类的实例. 3.结构图 简要分析结构图: ConcreteProduct

IOS设计模式之三:MVC模式

IOS设计模式之三:MVC模式 提到ios中的mvc不得不提2011秋季斯坦福课程的老头,他的iphone开发公开课是所有描述ios中mvc模式最为准确并且最为浅显易懂的. 模型-视图-控制器 这个模式其实应该叫做MCV,用控制器把model与view隔开才对,也就是model与view互相不知道对方的存在,没有任何瓜葛,他们就像一个团队里吵了架的同事,如果有项目需要他俩来参与,那么最好有第三者来管理他俩之间的沟通与协调.这个第三者就是控制器. 既然管理,那么姑且就把这个控制器提做项目经理吧,这