我们知道使用委托的设计模式可以实现一对一的通知关系,但是如果需要通知多个观察者状态变化又该如何呢?此时,需要实现观察者模式之类的内容,而不是实现委托者一对一的模式。

观察者模式定义了一个对象可以将另一个对象注册成自身观察者的模式,对象被注册成观察者后,任何观察者关注者事件都会在其发生时send给观察者。obj-c中实现观察者模式是通过NSNotificationCenter类实现的。该类为观察者对象和事件提供了一个全局调度系统。观察者可以向其注册观测系统中特定的事件;而被观察对象,在事件发生时,也可以发布通知到NSNotificationCenter,这样任何被观察者对象的通知可以发送到任何观察者对象,从而达到多对多关系的观察者模式。

为了完成观察者模式,一般要完成以下几个步骤:

1: 观察者使用NSNotificationCenter实例方法-addObserver将自身注册为特定事件的观察者;

2: 观察者要实现步骤1中注册的回调方法;

3: 被观察者对象要使用-postNotifiationName之类的发送方法发送消息;

4: 观察者最终要确保在释放时使用-removeObserver:将自己从NSNotificationCenter中移除。

下面用杜撰的代码来看看实际如何实现观察者模式。代码中狗仔队对于明星无聊中的对话可谓是八卦之极,star的每一句话都要设法得到啊。不过从实际代码看来,貌似明星也有意的想把这些对话内容传播出去啊!如果不想,那就类似于<<obj-c编程17:键值观察>>里的键值观察模式了哦。下面上代码:

#import <Foundation/Foundation.h>

#define msg(...) NSLog(__VA_ARGS__)

#define NOTIFICATION_NAME @"MY_NOTIFICATION"

@interface Star:NSObject{
	NSString *name;
}
	@property(readonly) NSString *name;
	-(void)talk:(NSString *)blabla;
@end

@implementation Star
	@synthesize name;

	-(id)initWithName:(NSString *)name_v{
		self = [super init];
		if(self){
			name = name_v;
		}
		return self;
	}

	-(void)talk:(NSString *)blabla{
		msg(@"%@ to say :%@",name,blabla);

		NSDictionary *secret = [NSDictionary dictionaryWithObject:blabla \
			forKey:@"words"];

		[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_NAME \
			object:self userInfo:secret];
	}
@end

@interface Dog:NSObject
	-(void)broadcast:(NSNotification *)note;
@end

@implementation Dog
	-(id)init{
		self = [super init];
		if(self){
			[[NSNotificationCenter defaultCenter] addObserver:self \
				selector:@selector(broadcast:) name:NOTIFICATION_NAME \
				object:nil];
		}
		return self;
	}

	-(void)broadcast:(NSNotification *)note{
		NSString *star_name = [[note object] name];
		NSString *words = [[note userInfo] objectForKey:@"words"];
		msg(@"star %@ sayed \"%@\"",star_name,words);
	}

	-(void)dealloc{
		[[NSNotificationCenter defaultCenter] removeObserver:self];
		//[super dealloc];
	}
@end

int main(int argc,char *argv[])
{
	@autoreleasepool{
		Star *star0 = [[Star alloc] initWithName:@"lucy"];
		Star *star1 = [[Star alloc] initWithName:@"jack"];
		Dog *dog = [[Dog alloc] init];

		[star0 talk:@"no shit!"];
		[star1 talk:@"that's right!"];
	}
	return 0;
}

运行结果是我们可以预料到的:

apple@kissAir: objc_src$./9

2014-08-03 21:05:11.830 9[910:507] lucy to say :no shit!

2014-08-03 21:05:11.831 9[910:507] star lucy sayed "no shit!"

2014-08-03 21:05:11.832 9[910:507] jack to say :that's right!

2014-08-03 21:05:11.832 9[910:507] star jack sayed "that's right!"

有人会说了,你这是1对多关系哦。多对多关系也很简单,狗仔队不止一只啊,我们再来创建1个,改变的代码如下:

int main(int argc,char *argv[])
{
	@autoreleasepool{
		Star *star0 = [[Star alloc] initWithName:@"lucy"];
		Star *star1 = [[Star alloc] initWithName:@"jack"];
		Dog *dog0 = [[Dog alloc] init];
		Dog *dog1 = [[Dog alloc] init];

		[star0 talk:@"no shit!"];
		[star1 talk:@"that's right!"];
	}
	return 0;
}

运行结果如下:

apple@kissAir: objc_src$./9

2014-08-03 21:32:43.513 9[973:507] lucy to say :no shit!

2014-08-03 21:32:43.514 9[973:507] star lucy sayed "no shit!"

2014-08-03 21:32:43.515 9[973:507] star lucy sayed "no shit!"

2014-08-03 21:32:43.515 9[973:507] jack to say :that's right!

2014-08-03 21:32:43.516 9[973:507] star jack sayed "that's right!"

2014-08-03 21:32:43.516 9[973:507] star jack sayed "that's right!"

obj-c编程18:多对多的观察者模式的更多相关文章

  1. pta编程(1-8)

    知识点:本次编程运用到的格式 #include<stdio.h> int main(void) { printf(); return 0; } 过程:1-3.没什么问题,就是注意字符的输入 ...

  2. Win64 驱动内核编程-18.SSDT

    SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...

  3. Qt编程18:Qt调色板QPalette的使用

    QPalette类有两个枚举类型, 枚举 1.ColorGroup CorGroup指的是3中不同的状态(什么时候设置颜色): 1>Active:获得焦点的状态. 2>Inactive:未 ...

  4. Linux编程 18 安装软件程序(yum工具对软件包安装,删除,更新介绍)

    一.   概述 本篇介绍在linux上见到的各种包管理系统(package management system,PMS)用来进行软件安装,管理,删除的命令行工具.PMS是利用一个数据库来记录各种相关内 ...

  5. Java Swing界面编程(18)---单行文本输入组件:JTextField

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/xuejiawei123/article/details/27565407 下面的程序与上一例有一点差 ...

  6. python面向对象编程(下)

    本篇详细介绍了Python 中类的成员.成员修饰符.类的特殊成员以及两个综合运用实例. 环境为:python3.5.1 类的成员 类的成员包括三大类:字段.方法和property属性 注:关于这三类成 ...

  7. Python面向对象进阶和socket网络编程-day08

    写在前面 上课第八天,打卡: 为什么坚持?想一想当初: 一.面向对象进阶 - 1.反射补充 - 通过字符串去操作一个对象的属性,称之为反射: - 示例1: class Chinese: def __i ...

  8. django(八)之数据库表的一对多,多对多表-增删改查

    单表操作 表记录的添加 方式一: Book() b=Book(name="python基础",price=99,author="yuan",pub_date=& ...

  9. python自动化开发-[第八天]-面向对象高级篇与网络编程

    今日概要: 一.面向对象进阶 1.isinstance(obj,cls)和issubclass(sub,super) 2.__setattr__,__getattr__,__delattr__ 3.二 ...

随机推荐

  1. 06 获取Activity的栈管理器

    代码 <span style="font-size:18px;">package com.fmy.day8_29task.util; import java.util. ...

  2. UNIX网络编程——关于socket阻塞与非阻塞情况下的recv、send、read、write返回值

    1.阻塞模式与非阻塞模式下recv的返回值各代表什么意思?有没有 区别?(就我目前了解阻塞与非阻塞recv返回值没有区分,都是 <0:出错,=0:连接关闭,>0接收到数据大小,特别:返回 ...

  3. Android的ProgressBar进度条-android学习之旅(三十一)

    ProgressBar 简介 ProgressBar是一种很常用的Ui,用于给复杂的操作显示进度,提供更好的用户相应.使用setProgress()incrementProgressBy()来设置进度 ...

  4. Android初级教程理论知识(第六章广播接受者)

    总体概述: 广播接收者 现实中:电台要发布消息,通过广播把消息广播出去,使用收音机,就可以收听广播,得知这条消息 Android中:系统在运行过程中,会产生很多事件,那么某些事件产生时,比如:电量改变 ...

  5. A*寻路算法入门(七)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  6. Java线程的状态

    Java线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在于Thread中的State枚举中,如下所示: public enum State { /** * 至今尚未启动的线程处于这种状 ...

  7. 摆脱命令行,Ubuntu下配置Android开发环境

    作者:宋志辉 微博:weibo.com/askzhihui/ 安装所需工具 一.新立得 新立得(Synaptic)是Debian和Ubuntu Linux操作系统的包管理工具apt的图形化前端. 它结 ...

  8. Android Studio 使用 Gradle 打包 Jar

    Android Studio 打 Jar 包一直是一个麻烦的事,按照网上现有的教程,打包一个混淆的 jar 需要完成下列步骤: 1.将 plugin 修改为 library 后 build 出 aar ...

  9. RabbitMQ消息队列(七):适用于云计算集群的远程调用(RPC)

            在云计算环境中,很多时候需要用它其他机器的计算资源,我们有可能会在接收到Message进行处理时,会把一部分计算任务分配到其他节点来完成.那么,RabbitMQ如何使用RPC呢?在本篇 ...

  10. C#attribute-----------初级

    前言: attribute是 .net FrameWork 提出的技术,可以为自己的代码添加注解,从而实现些特殊功能. 一. attribute功能 attribute被译作特性,既然是特性,必然功能 ...