zoukankan      html  css  js  c++  java
  • 对象去耦的方法之一:观察者模式

    观察者模式是指一个对象状态发生改变,会通知正在对它进行观察的对象。观察者模式最常见的两种:KVO,NSNotification。

    首先关于KVO:(这里注意KVO和KVC都基于runtime的动态机制)

    观察者是在被观察者内进行注册的,同时观察者和被观察者都要实现NSKeyValueObserving协议(NSObject已默认实现)

    例子:

    被观察者:
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. self.watcher = [TestWatche alloc];   //注册观察者(1) [self addObserver:self.watcher forKeyPath:@"state" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"pass content"]; self.state = @"launch"; return YES; } - (void)applicationDidEnterBackground:(UIApplication *)application { self.state = @"backgroud"; }

    观察者:
    #import "TestWatche.h"
    @implementation TestWatche
    //实现观察方法(2)
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
        NSLog(@"state change:%@",change);
    }
    @end
    //移除方法(3)
    - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

    实现分析:

    使用观察者模式需要被观察者的配合,当被观察者的状态发生变化的时候通过事先定义好的接口(协议)通知观察者。在KVO的使用中我们并不需要向被观察者添加额外的代码,就能在被观察的属性变化的时候得到通知,这个功能是如何实现的呢?同KVC一样依赖于强大的Runtime机制。

    系统实现KVO有以下几个步骤:

    • 当类A的对象第一次被观察的时候,系统会在运行期动态创建类A的派生类。我们称为B。
    • 在派生类B中重写类A的setter方法,B类在被重写的setter方法中实现通知机制。
    • 类B重写会 class方法,将自己伪装成类A。类B还会重写dealloc方法释放资源。
    • 系统将所有指向类A对象的isa指针指向类B的对象。

    KVO同KVC一样,通过 isa-swizzling 技术来实现。当观察者被注册为一个对象的属性的观察对象的isa指针被修改,指向一个中间类,而不是在真实的类。其结果是,isa指针的值并不一定反映实例的实际类。

    所以不能依靠isa指针来确定对象是否是一个类的成员。应该使用class方法来确定对象实例的类。

    关于Notification:

    不同于KVO,这里观察者是在观察者内部自己注册的。

    被观察者:
    - (void)applicationDidEnterBackground:(UIApplication *)application { [[NSNotificationCenter defaultCenter]postNotificationName:@"APPTerminate" object:self]; }
    观察者:
    @implementation ViewController
    - (void)viewDidLoad {
        [super viewDidLoad];
        //注意此处的selector有参数,要加冒号
        [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(doSomething:) name:@"APPTerminate" object:nil];
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        [[NSNotificationCenter defaultCenter]removeObserver:self];
        // Dispose of any resources that can be recreated.
    }
    
    #pragma mark -处理通知
    -(void)doSomething:(NSNotification*)notification{
        NSLog(@"收到通知");
    }
    @end
     

     引用:

    http://www.cnblogs.com/zy1987/p/4616764.html

    https://segmentfault.com/a/1190000000768605

  • 相关阅读:
    (转)Android 序列化对象接口Parcelable使用方法
    (转)在android中画圆形图片的几种办法
    (转)有趣的动画视图集合:Android View Animations
    (转)如何将一个Android工程作为另一个Android工程的库来使用
    (转)解析BroadcastReceiver之你需要了解的一些东东
    (转)Android系列之Fragment(一)----Fragment加载到Activity当中
    (转)推荐安卓开发神器(里面有各种UI特效和实例)
    (转)android仿win8 metro磁贴布局,可以随便的拖动以改变布局的位置
    (转)Android TextView中文字通过SpannableString来设置超链接、颜色、字体等属性以及自定义链接到下一个Activity
    Android 官方文档 Training部分翻译
  • 原文地址:https://www.cnblogs.com/encoreMiao/p/6567291.html
Copyright © 2011-2022 走看看