iOS应用开发中使用设计模式中的观察者模式的实例

在软件开发中,无论是那种高级语言中总会伴随着一些最为常用的设计模式,即便就如iOS开发中与我们打交道最多的无非就是单例模式、观察者模式和工厂模式了,当然了其他的设置模式也同样存在在编程的很多地方。下面就就让我们简单的了解下观察者模式吧!
观察者模式本质上时一种发布-订阅模型,用以消除具有不同行为的对象之间的耦合,通过这一模式,不同对象可以协同工作,同时它们也可以被复用于其他地方Observer从Subject订阅通知,ConcreteObserver实现重现ObServer并将其重载其update方法。一旦SubJect的实例需要通知Observer任何新的变更,Subject会发送update消息来通知存储在其内部类中所注册的Observer、在ConcreteObserver的update方法的实际实现中,Subject的内部状态可被取得并进行后续处理。其类图如下:

由上面我们可以发现观察者模式无非在是定义对象间的一种一对多的依赖关系,并且当一个对象的状态发生改变的时候,所有依赖于它的对象都会得到通知且自动更新。即如果Subject允许其他观察者(实现了观察者接口的对象)对这个Subject的改变进行请阅,当Subject发送了变化,那么Subject会将这个变化发送给所有的观察者,观察者就能对Subject的变化做出更新。其时序图如下

通过上面的观察我们可以发现如果用N个Observer来拓展Subject的行为,这些Observer具有处理存储在Subject中的信息的特定实现,这样也就实现了前面所说的消除不同对象间的耦合的功能了。
那么了解了这些我们可能就会更像了解下我们在什么时候才会去使用观察者模式呢?
当需要将改变通知所有的对象时,而你又不知道这些对象的具体类型
改变发生在同一个对象中,并需要改变其他对象将相关的状态进行更新且不知道有多少个对象。
而同样的在我们日常的开发中在Cocoa Touch框架中的的两种经常打交道的技术KVO与通知都实现了观察者模式,所以下面我们讨论的重点也就是基于这两个方面的。
通知
言归正传,在Cocoa Touch框架中NSNotificationCenter和NSNotification对象实现了一对多的模型。通过NSNotificationCenter可以让对象之间进行通讯,即便这些对象之间并不认识。下面我们来看下NSNotificationCenter发布消息的方法:

代码如下:

NSNotification  * subjectMessage = [ NSNotification  notificationWithName:@"subjectMessage"  object: self];
    NSNotificationCenter  * notificationCenter = [ NSNotificationCenter  defaultCenter];
    [notificationCenter postNotification:subjectMessage];

通过上面的代码我们创建了一个名为subjectMessage的NSNotification对象,然后通过notificationCenter来发布这个消息。通过向NSNotificationCenter类发送defaulCenter消息,可以得到NSNotificationCenter实例的引用。每个进程中只有一个默认的通知中心,所以默认的NSNotificationCenter是个单例对象。如果有其他观察者定于了其对象的相关事件则可以通过以下的方法来进行操作:

代码如下:

NSNotificationCenter  * notificationCenter1 = [ NSNotificationCenter  defaultCenter];
    [notificationCenter addObserver: self  selector: @selector(update:) name:@"subjectMessage"  object: nil ];

经过以上步骤我们已经向通知中心注册了一个事件并且通过selector制定了一个方法update:下面我们可以实现以下这个方法

代码如下:

- (void)update:(NSNotification*)notification{

if ([[notification name] isEqualToString:@"subjectMessage"]) {
            NSLog(@"%@",@"猴子派来的救兵去哪了?");

}
}

当然最后如果我们需要对监听进行销毁

代码如下:

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

实例
抽象主题协议:

代码如下:

#import <Foundation/Foundation.h> 
@class Observer; 
 
/*!
 *  抽象主题协议
 *
 *  @since V1.0
 */ 
@protocol Subject <NSObject> 
 
@required 
 
/*!
 *  增加观察者
 *
 *  @param observer 观察者实例
 *
 *  @since V1.0
 */ 
-(void)attach:(Observer*) observer; 
/*!
 *  移除观察者
 *
 *  @param observer 观察者实例
 *
 *  @since V1.0
 */ 
-(void)detach:(Observer*) observer; 
/*!
 *  为观察者发送通知
 *
 *  @since V1.0
 */ 
-(void)notifyObservers; 
 
@end

观察者协议:

代码如下:

#import <Foundation/Foundation.h> 
 
/*!
 *  观察者协议
 *
 *  @since V1.0
 */ 
@protocol Observer <NSObject> 
 
@required 
-(void)update; 
 
@end

具体的观察者类:

代码如下:

#import <Foundation/Foundation.h> 
#import "Observer.h" 
 
/*!
 *  具体的观察者类
 *
 *  @since V1.0
 */ 
 
@interface ConcreteObserver : NSObject<Observer> 
 
@end

具体主题类:

代码如下:

#import <Foundation/Foundation.h> 
#import "Subject.h" 
 
/*!
 *  具体主题类
 *
 *  @since V1.0
 */ 
@interface ConcreteSubject : NSObject<Subject> 

    NSMutableArray *observers; 

@property(nonatomic,strong)NSMutableArray* observers; 
/*!
 *  单例构建自身对象
 *
 *  @return 自身对象
 *
 *  @since V1.0
 */ 
+(ConcreteSubject*)shareConcreteSubject; 
 
@end

了解过通知之后我们来看一下KVO
KVO是Cocoa提供的一种称为键值观察的机制,对象可以通过它得到其他对象特定属性的变更通知。而这个机制是基于NSKeyValueObserving非正式些,Cocoa通过这个协议为所有遵循协议的对象提供了一种自动化的属性监听的功能。
虽然通知和KVO都可以对观察者进行实现,但是他们之间还是略有不同的,由上面的例子我们可以看出通知是由一个中心对象为所有观察者提供变更通知,主要是广义上关注程序事件,而KVO则是被观察的对象直接想观察者发送通知,主要是绑定于特定对象属性的值。下面我们通过一个简单的例子来了解下他的一些是使用方法
首先我们有Hero这个模型

代码如下:

@property (nonatomic,copy) NSString * name;@property (nonatomic,copy) NSString * title;@property (nonatomic,assign) NSUInteger age;

在控制其中我们将其初始化并赋值

代码如下:

self.hero = [[Hero alloc] init];
    self.hero.name = @"赵云";
    self.hero.title = @"将军";
    self.hero.age = 87;

现在我们的这个对象基本有值了,那么我们将这个对象的name监听下他的改变

代码如下:

[self.hero addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

触发通知并将值改变

代码如下:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    self.hero.name = @"张飞";
}

在制定的回调函数中,处理收到的更改通知

代码如下:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if([keyPath isEqualToString:@"name"])
    {
        NSLog(@"赋值后--%@",self.hero.name);
        NSLog(@"新的值--%@",change[@"new"]);
        NSLog(@"以前的值--%@",change[@"old"]);

}
}

回调打印如下:

最后注销观察者

代码如下:

- (void)dealloc{
    [self.hero removeObserver:self forKeyPath:@"name"];
}

到了这里观察者模式中常用的KVO及通知的内容就到这里,不过要知道这里谈及的只是最基础的用法,后面我们可能还是有更加深入的探究,或者在后续中可能还会对比iOS中的代理以及Block来探寻下iOS中的消息传递机制,再或者像Swift中的didSet、willSet的属性监听的方法,这些都是很好玩的内容,不是么?

(0)

相关推荐

  • 设计模式中的Memento备忘录模式的在iOS App开发中的运用

    备忘录模式.顾名思义,备忘录模式的初衷就是为了返回上一个状态而设计的.从名字看起来一目了然,好吧,还是老样子,先给出定义. 备忘录(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.这样以后就可将该对象恢复到原先保存的状态. 定义看起来搞的很专业,其实就是保存上一个状态,以便日后恢复用.好比是在玩游戏,在打大Boss之前担心第一次打不过,先存个盘,万一玩儿完了,还可以恢复状态重新PK. 下面给出类结构图. Originator(原发器):记录当前时刻的

  • iOS App设计模式开发中策略模式的实现示例

    这次介绍一下策略模式(Strategy Pattern),相比之下是一种比较简单的模式.它也叫政策模式(Policy Pattern). 策略模式使用的就是面向对象的继承和多态机制,其他的没有什么玄机.策略模式适合使用在: 1. 多个类只有在算法或行为上稍有不同的场景. 2. 算法需要自由切换的场景. 3. 需要屏蔽算法规则的场景. 使用策略模式当然也有需要注意的地方,那么就是策略类不要太多,如果一个策略家族的具体策略数量超过4个,则需要考虑混合模式,解决策略类膨胀和对外暴露问题.在实际项目中,

  • iOS App设计模式开发之适配器模式使用的实战演练

    相信做App开发的同学,对于一些第三方的统计分析.错误收集等SDK应该都不陌生.就目前而言市面上也有许多相同功能的产品,眼花缭乱,让人无法抉择选哪一款SDK才是最靠谱的.那就随便先选一款试试用吧! 那么问题来了:如果项目都快做完了结果发现这款SDK实在坑爹,不仅扩展性差,还经常让App Crash,那你是不是会想到替换掉这个SDK? OK,那我们就换另一个试试,下载SDK下来,一看,傻眼了,设计风格,封装模块完全不一样,于是乎我们就到项目中全局搜索找到之前的SDK代码干掉,然后重新再到各种地方用

  • iOS应用设计模式开发中对简单工厂和工厂方法模式的运用

    简单工厂模式 正如此模式的名称一样,简单工厂模式基本上是所有设计模式里最简单的一种,类与类之间的关系一目了然.这次我就用很多地方经常举的例子--计算器,来说明这个模式.首先给大家展示一下类之间的结构图: 通过这张结构图,可以清晰的看到,加法类.减法类.乘法类.除法类继承自运算类,简单工厂类依赖于运算类的实例化来实现相应的运算功能,好的,看起来并不复杂,让我们直接展示一下代码吧(鉴于目前点点不支持Objective C的代码高亮,所以就直接写啦,尽量保持整齐吧.另,为了照顾像我一样基础不是很好的同

  • 实例讲解iOS应用的设计模式开发中的Visitor访问者模式

    为了方便向大家展示,先给出简短的定义: 访问者模式(Visitor),表示一个作用于某对象结构中的各元素的操作.它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作. 紧接着,给出其类结构图. 访问者模式适用于数据结构相对稳定的系统,它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作结合可以相对自由地演化. 访问者模式的目的是要把处理从数据结构分离出来.很多系统可以按照算法和数据结构分开,如果这样的系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,

  • iOS App使用设计模式中的模板方法模式开发的示例

    模板方法模式的核心思想就是通过把不变的行为搬移到超类,去除子类中的重复代码来体现它的优势.其实,模板方法模式就是提供了一个很好的代码复用平台. 首先,还是先简单看一下定义: 模板方法模式,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 下面和给大家展示一下类的结构图: 其实,结构很简单,只有两层关系,核心思想就是把公共方法向上提到父类中.代码实现起来也不复杂.下面还是老样子,向大家简单展示一下代码如何实现. 首先是一

  • 举例讲解iOS应用开发中对设计模式中的策略模式的使用

    策略模式是一种常见的软件设计模式,这里简单得介绍一下策略模式并用IOS简单实现一下. 所谓的策略模式,顾名思义是要采用不同的策略的.一般来说,在不同的情况下,处理某一个问题的方法也不一样.比如说对字符串的排序和对数字的排序,虽然用的都是快排,但是显然不可能使用一段通用的代码.有人说java里面的compareTo可以做到,但如果考虑这么一个问题:同样是出门旅行,老年人身体虚弱,需要大量的休息,而孩子则是精力充沛,希望玩到更多的景点.如何在同一模式下表达以上信息.采用合理的设计模式进行封装而不是大

  • 实例讲解设计模式中的命令模式在iOS App开发中的运用

    命令模式封装一个请求或行为作为一个对象.封装的请求比原的更加灵活,可以在对象之间传递,储存,动态修改,或放入一个队列. 那么让我们简要的说一下命令模式的特点. 它能比较容易地设计一个命令队列: 在需要的情况下,可以较容易地将命令记入日志: 允许接收请求地一方决定是否要否决请求: 可以容易地实现对请求地撤销和重做: 由于加进新地具体命令类不影响其他的类,因此增加新的具体命令类很容易: 把请求一个操作的对象与知道怎么执行一个操作的对象分隔开. 下面给出基本的类结构图: 上面这张图是命令模式的类结构的

  • 实例讲解如何在iOS应用开发中使用设计模式中的代理模式

    代理模式是OC中一种常见的设计模式,那么什么是代理模式呢?举个栗子,假设你是一个日发货量过万的淘宝卖家(A),但是每天的派件不可能你本人或者让你的员工去派件,因此你发布了一条信息(B),上面注明各种要求,各大快递公司看到有那么大的利益纷纷上门沟通,最后你选择了一件快递公司(C).那么在上面的例子中,我们即是委托人,发布的信息即协议(protocol),上面规定了派件人需要完成的事,而最后选择的快递公司也就是代理人(delegate),代理我们去派件. 类图: 根据以上类图,可以知道在代理模式中的

  • C++编程中使用设计模式中的policy策略模式的实例讲解

    在看<C++设计新思维>的时候,发现在一开始就大篇幅的介绍策略模式(policy),策略模式不属于经典设计模式中的一种,但是其实在我们日常的开发中是必不可少的.policy,策略,方针,这里的意思是指把复杂功能的类尽量的拆分为功能单一的简单类的组合,简单的类只负责单纯行为或结构的某一方面.增加程序库的弹性,可复用性,可扩展性.policy是一个虚拟的概念,他定义了某一类class的一些接口规范,并不与C++语法的关键字对应,只是一个抽象的概念. 实例1: //policy模式的常见使用实例sm

  • C#编程中使用设计模式中的原型模式的实例讲解

    一.引言 在软件系统中,当创建一个类的实例的过程很昂贵或很复杂,并且我们需要创建多个这样类的实例时,如果我们用new操作符去创建这样的类实例,这未免会增加创建类的复杂度和耗费更多的内存空间,因为这样在内存中分配了多个一样的类实例对象,然后如果采用工厂模式来创建这样的系统的话,随着产品类的不断增加,导致子类的数量不断增多,反而增加了系统复杂程度,所以在这里使用工厂模式来封装类创建过程并不合适,然而原型模式可以很好地解决这个问题,因为每个类实例都是相同的,当我们需要多个相同的类实例时,没必要每次都使

  • iOS应用开发中使用设计模式中的观察者模式的实例

    在软件开发中,无论是那种高级语言中总会伴随着一些最为常用的设计模式,即便就如iOS开发中与我们打交道最多的无非就是单例模式.观察者模式和工厂模式了,当然了其他的设置模式也同样存在在编程的很多地方.下面就就让我们简单的了解下观察者模式吧! 观察者模式本质上时一种发布-订阅模型,用以消除具有不同行为的对象之间的耦合,通过这一模式,不同对象可以协同工作,同时它们也可以被复用于其他地方Observer从Subject订阅通知,ConcreteObserver实现重现ObServer并将其重载其updat

  • iOS App开发中使用设计模式中的单例模式的实例解析

    一.单例的作用 顾名思义,单例,即是在整个项目中,这个类的对象只能被初始化一次.它的这种特性,可以广泛应用于某些需要全局共享的资源中,比如管理类,引擎类,也可以通过单例来实现传值.UIApplication.NSUserDefaults等都是IOS中的系统单例. 二.单例模式的两种写法 1,常用写法 #import "LGManagerCenter.h" static LGManagerCenter *managerCenter; @implementation LGManagerCe

  • 深入解析iOS应用开发中对设计模式中的桥接模式的使用

    引言 在项目开发中,我们会遇到这样的一种场景:某些类型由于自身的逻辑,往往具有两个或多个维度的变化,比如说大话设计模式书中所说的手机,它有两个变化的维度:一是手机的品牌,可能有三星.苹果等:二是手机上的软件,可能有QQ.微信等.如何应对这种"多维度的变化"?怎样利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度?这就是本章桥接模式所要解决的问题. 何为桥接模式? 桥接模式的目的是把抽象层次结构从其实现中分离出来,使其能够独立变更.抽象层定义了供客户端使

  • 详解iOS应用开发中使用设计模式中的抽象工厂模式

    概述 我们知道简单工厂模式的优点是去除了客户端与具体产品的依赖,缺点是违反了"开放-关闭原则":工厂方法模式克服了简单工厂模式的缺点,将产品的创建工作放到具体的工厂类,每个工厂类负责生成一个产品.但是在实际应用中,一个工厂类只创建单个产品的情况很少,一般一个工厂类会负责创建一系列相关的产品,如果我们要设计这样的系统,工厂方法模式显然不能满足应用的需求,本章要介绍的抽象工厂模式,可以很好地解决一系列产品创建的问题. 定义 "提供一个创建一系列相关或相互依赖对象的接口,而无需指定

  • 解析iOS应用开发中对设计模式中的抽象工厂模式的实现

    概述 抽象工厂模式是对象的创建模式,它是工厂方法模式的进一步推广. 假设一个子系统需要一些产品对象,而这些产品又属于一个以上的产品等级结构.那么为了将消费这些产品对象的责任和创建这些产品对象的责任分割开来,可以引进抽象工厂模式.这样的话,消费产品的一方不需要直接参与产品的创建工作,而只需要向一个公用的工厂接口请求所需要的产品. 通过使用抽象工厂模式,可以处理具有相同(或者相似)等级结构中的多个产品族中的产品对象的创建问题.如下图所示: 根据产品角色的结构图,就不难给出工厂角色的结构设计图. 可以

  • iOS应用开发中运用设计模式中的组合模式的实例解析

    何为组合模式?     组合模式让我们可以把相同基类型的对象组合到树状结构中,其中父节点包含同类型的子节点.换句话说,这种树状结构形成"部分--整体"的层次结构.什么是"部分--整体"的层次结构呢?它是既包含对象的组合又包含叶节点的单个对象的一种层次结构.每个组合体包含的其他节点,可以是叶节点或者其他组合体.这种关系在这个层次结构中递归重复.因为每个组合或叶节点有相同的基类型,同样的操作可应用于它们中的每一个,而不必在客户端作类型检查.客户端对组合与叶节点进行操作时

随机推荐