谈KVC、KVO(重点观察者模式)机制编程
一不小心,小明在《跟着贝尔去冒险》这个真人秀节目中看到了“一日警察,一世警察”的Laughing哥,整个节目除了贝尔吃牛睾丸都不用刀叉的不雅餐饮文化外,还是镜头少普通话跟小明一样烂的Laughing Sir那种冷静和沉着稳定留下了深刻印象,不由想起电视剧《学警狙击》中为了不暴露钟立文的身份,要求向自己补一枪的警匪卧底巅峰推动者--Laughing 哥。
那么,卧底这样的工作,在我们程序里有没有呢?答案是肯定的,观察者模式。

一.基本概念
1)KVC概念
- KVC全称Key-value coding.
- 一个非正式的Protocol,提供一种机制来间接访问对象的属性.
官方文档提供对KVC很准确的描述
Key-value coding is a mechanism for accessing an object’s properties indirectly, using strings to identify properties, rather than through invocation of an accessor method or accessing them directly through instance variables. In essence, key-value coding defines the patterns and method signatures that your application’s accessor methods implement.
2)KVO概念
- KVO全称Key-Value Observing。
- 典型的观察者模式承载者。
- 基于监控键值发生变化,通知观察者。
- KVO 就是基于 KVC 实现的关键技术之一。
官方文档提供对KVO很准确的描述
Key-value observing provides a mechanism that allows objects to be notified of changes to specific properties of other objects. It is particularly useful for communication between model and controller layers in an application.
二.KVC和KVO的作用
Laughing哥上场了,先看看怎么做卧底,首先,Laughing哥先得符合古惑仔行为准则混入黑帮;接着,除了放高利贷和Disco业务外最重的是挤兑从台湾出狱的世孝,选择站在亦天内心的一边得到足够多的信任;最后,凭借“一日警察,一世警察”赤诚初心,秉公执法端掉亦天和制毒窝点。
那么,你觉度Laughing Sir的作用是什么?
1. 接近需要得到信息隐秘或不隐秘的使用场所。
2. 直接监视信息的变化。
3. 当产生了有用的信息后,那马上通知汇报。
如果亦天制作的毒品比作信息,普通警察只能通过get方式属性,更重要是不知道他什么时候发生了变化。卧底Laughing Sir完美扮演的就是KVC和KVO机制,为什么说完美?KVC是可以直接通过路径获取对应的键的值,KVO的观察通知部分就对应Laughing Sir的监视和汇报,如果Laughing Sir变节了或者没有意志做下去了,那就只能是KVC能获取到信息,但不能通知上级信息的变化,就没有了一个经典的卧底角色Laughing了。
三.JAVA中的观察着模式
Sun公司早早就把观察者模式视为重要的模式,并在Java中提供方便的接口Observer和类Observable。这个地方注意一下,Observer是一个接口,Observable是一个类。因为很容易先入为主,XXXable第一反应是接口。如果看过《设计模式之禅》这本书的人,自然想起书中举的例子是李斯监视同窗韩非子的一举一动汇报给秦始皇。并且书中的Observer和Observable自定义定义刚好相反,注意下即可。为什么提Java,继续看吧。
四.代码实现
1. KVC属性读取和修改
1)Sense:
警官:梁笑棠,从今天开始 ,你的生命属于社会的,清楚吗?
Laughing Sir:清楚。
警官:出了这个学堂,你要叫Laughing 哥,记好了吗?
Laughing Sir:Yes sir。
警官:你妹,大声点。
Laughing Sir:_____
程序中,Laughing Sir被派于卧底工作前,需要把Laughing Sir
的名字属性值更换成Laughing哥
.我们就从这个地方开始练练手预热做卧底的体验吧。
2)Step:
①通过路径方式获取属性值
NSString *preName = [laughingSir valueForKey:@"name"];
②修改属性值
[laughingSir setValue:@"laughing 哥" forKey:@"name"];
3)Show Code:
NSString* exchangeName(LaughingSir *laughingSir){ NSString *preName = [laughingSir valueForKey:@"name"];
NSLog(@"laughing的旧名字:%@",preName); [laughingSir setValue:@"laughing 哥" forKey:@"name"]; NSString *newName = [laughingSir valueForKey:@"name"];
NSLog(@"laughing的新名字:%@",newName); return newName;
}
2.KVO观察者模式演绎
1)Sense:
亦天可能进行制毒。。。 Laughing Sir开始监控亦天 报告上级亦天制毒数:___
程序中,Laughing Sir开始观察YiTian这个实体类中的narcotics属性,一旦亦天制作出毒品,就马上observeValueForKeyPath通知上级,看看如下的具体实现。
2)Step:
①对被观察者添加观察 [self.yiTian addObserver:self forKeyPath:@"narcotics" options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld context:nil];
②实现观察结果处理方法 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
//汇报上级
}
3)Show Code:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
if([keyPath isEqualToString:@"narcotics"]){ NSNumber *narcoticsN = [change objectForKey:@"new"];//修改之后的最新值
NSInteger narcotics = [narcoticsN integerValue];
if (narcotics>) {
if (self.delegate!=nil&&[self.delegate respondsToSelector:@selector(reportYitian:)]) {
[self.delegate reportYitian:narcotics];
}
}
}
}
注意:留意下[change objectForKey:@"new"]其中这个new是指新赋予narcotics这个属性的值,当然也有一个old而不是[change objectForKey:@"narcotics"];narcotics是毒品意思。
3.Java实现观察者模式
这里我就直接显示关键代码了,不做过多说明,对比了解和学习。
/**
* 亦天实体类
* @author minggo
* @time 2016年4月1日 上午10:24:15
*/
public class YITian extends Observable { private Observer observer;
private int narcotics; @Override
public synchronized void addObserver(Observer o) {
super.addObserver(o);
this.observer = o;
} public void MakeNarcotics(){
for (int i = ; i <; i++) {
narcotics++;
if (observer!=null) {
observer.update(this, narcotics);
}
}
} }
留意Laughing Sir实体类的@override方法
/**
* Laughing Sir实体类
* @author minggo
* @time 2016年4月1日 上午9:58:36
*/
public class LaughingSir implements Observer{
@Override
public void update(Observable o, Object arg) {
if (o instanceof YITian) {
System.out.println("监视到亦天制毒"+arg+"kg");
}
}
public void watchOverYiTian(YITian yiTian){
yiTian.addObserver(this);
}
}
最后是测试main方法
/**
* 观察者模式
* @author minggo
* @time 2016年4月1日 上午10:36:37
*/
public class TestOberving { public static void main(String[] args) { YITian yiTian = new YITian();
LaughingSir laughingSir = new LaughingSir(); //Laughing Sir卧底开始监视亦天的一举一动
laughingSir.watchOverYiTian(yiTian);
System.out.println("Laughing Sir卧底开始监视亦天的一举一动"); System.out.println("-----------亦天开始制作毒品--------");
//亦天开始制毒
yiTian.MakeNarcotics();
System.out.println("-----------亦天结束制作毒品--------");
}
}
五.现状下观察者模式的重要性
就犹如Laughing哥这样的角色,观察者模式在实际应用中起到重要的作用。无论你之前发现了,还是现在察觉到它的不可忽视。移动开发的MVVM开发架构思想中的重要解耦页面部分,就是观察者模式实现数据绑定,即时刷新数据。这个在iOS中KVO和Android使用Java的Observer接口都异曲同工之意,RxJava的响应是编程的基本思想也是观察者模式之艺术。
现状下的热门的移动开发的关键字,透漏出观察者模式显得越来越重要。其中就包括面试门槛,曾经面试过Android开发者还是iOS开发者,问到观察者这个模式可有了解?有回答iOS观察就是KVO,Java的就是在被观察对象添加回调接口,也有说过《设计模式之禅》中的韩非子被李斯监视的例子。
今天,有多了一个,Laughing哥卧底神话,个人感情建议使用这个例子,呵呵~。
六.效果图更直观

七.源码下载地址更详细
https://github.com/minggo620/iOSObserving.git
谈KVC、KVO(重点观察者模式)机制编程的更多相关文章
- KVC/KVO原理详解及编程指南
一.简介 1.KVC简介 2.KVO简介 二.KVC相关技术 1.Key和Key Path 2.点语法和KVC 3.一对多关系(To-Many)中的集合访问器方法 4.键值验证(Key-Value V ...
- 【转】 KVC/KVO原理详解及编程指南
原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 前言: 1.本文基本不讲KVC/KVO的用法,只结合网上的资料说说对这种技术的 ...
- 转:KVC/KVO原理详解及编程指南
作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或 ...
- KVC, KVO 实现原理
Key-Value Coding: 键值编码 (KVC) 方法调用: // 对象属性 // 类似: Person -> name setValue: forKey: // 对象的属性或者 属性的 ...
- 浅谈Linux中的信号处理机制(二)
首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...
- IOS开发之KVC KVO KVB
KVC(Key Value Coding) KVO(Key Value Observing) KVB(Key Value Binding) KVO是Cocoa的一个重要机制,他提供了观察某一属性变化的 ...
- kvc/kvo复习
kvc/kvo复习 1 小问题 '[<XMGPerson 0x7fb8a8f30220> setValue:forUndefinedKey:]: this XMGPerson * pers ...
- 阶段性总结⓵触摸事件&手势识别⓶Quartz2D绘图⓷CALayer图层⓸CAAnimation⓹UIDynamic UI动力学⓺KVC&KVO
知识点复习 1. 触摸事件&手势识别 1> 4个触摸事件,针对视图的 2> 6个手势识别(除了用代码添加,也可以用Storyboard添加) 附加在某一个特定视图上的, ...
- Vue总结第五天:vue-router (使用模块化(创建Vue组件)机制编程)、router-link 标签的属性、路由代码跳转、懒加载、路由嵌套(子路由)、路由传递数据、导航守卫)
Vue总结第五天:vue-router ✿ 路由(器)目录: □ vue中路由作用 □ vue-router基本使用 □ vue-router嵌套路由 □ vue-router参数传递 □ ...
随机推荐
- web服务器分析与设计(五)--一些总结
随着年龄与经验的增加,对于软件方面的分析与设计也会有一些新的认识.下面做个近期的总结: 1,关于到底用不用作设计的问题: 在最近两个公司,原有人马是不会作设计(我自己的感觉),也察觉不到作设计的任何冲 ...
- [Hive - Tutorial] Data Units 数据存储单位
Data Units In the order of granularity - Hive data is organized into: 数据库.表.分区.桶 Databases: Namespac ...
- 你真的了解一段Java程序的生命史吗
作为一名程序猿 ,我们每天都在写Code,但你真的了解它的生命周期么?今天就来简单聊下它的生命历程,说起一段Java Code,从出生到game over大体分这么几步:编译.类加载.运行.GC. 编 ...
- homework-01 "最大子数组之和"的问题求解过程
写在前面:我的算法能力很弱,并且也是第一次写博文,总之希望自己能在这次的课程中学到很多贴近实践的东西吧. 1.这次的程序是python写的,这也算是我第一次正正经经地拿python来写东西,结果上来说 ...
- 现代程序设计 homework-05
本次作业要求设计服务器和客户端,由于之前对网络编程是一窍不通,上上节课听宗学长讲述Tcp的时候心里想这个东西还真是高大上啊一点儿都听不懂,但是上个周末看了看C#网络编程的博客和书之后,发现这个东西入门 ...
- JDBC学习笔记(10)——调用函数&存储过程
如何使用JDBC调用存储在数据库中的函数或存储过程: * 1.通过COnnection对象的prepareCall()方法创建一个CallableStatement * 对象的实例,在使用Con ...
- 【C语言】-一维数组
数组: 数组是一系列相同类型的有序数据的集合,数组中的每一个元素都是同一个数据类型,所有元素共用一个名字,用下标来区别数组中的每一个元素. C语言中,数组属于构造数据类型.一个数组中含有多个数组元素, ...
- codeforces 624B Making a String
Making a String time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...
- 行内onclick使用遇坑--------作用域与传入字符串
问题一:行内onclick触发的函数放在$(funtion(){})内报错,错误代码如下: <input type="button" value="确定" ...
- Android中图表AChartEngine学习使用与例子
很多时候项目中我们需要对一些统计数据进行绘制表格,更多直观查看报表分析结果.基本有以下几种方法: 1:可以进行android api进行draw这样的话,效率比较低 2:使用开源绘表引擎,这样效率比 ...