美文网首页Android开发Kotlin编程Kotlin代码日记
什么,属性也能有观察者模式?

什么,属性也能有观察者模式?

作者: 小小小小小粽子 | 来源:发表于2019-04-07 22:39 被阅读2次

在前面的博文中,我们一起探究了类代理代理属性,一起深入了解了它们的实现机制,顺便还讨论了下标准库的玩儿法:lazy函数,其实除了lazy这种懒加载的函数,还有用代理属性实现类似观察者模式的机制,我们一起来看一下。

标准库给我们提供的是Delegates.observable,它的使用方法如下:

fun main(args:Array<String>){
     var name by Delegates.observable("王小明") { property, oldValue, newValue ->
  println("$oldValue -> $newValue")
     }
  name="海东"
  name="剑"
  }

observable函数很简单,第一个参数我们传入一个初始值,第二个参数我们传入一个lambda,可以对旧值新值做一些操作,每次赋值都会调用我们的lambda,我们这里在赋值的时候就会打印出旧值新值,事实上你可以在这里做你想做的任何操作。

很神奇又很简单,总让人好奇是怎么实现的:

public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
        ReadWriteProperty<Any?, T> =
    object : ObservableProperty<T>(initialValue) {
        override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
    }

我们看到这个方法返回了我们熟悉的ReadWriteProperty接口的对象,实际上是个ObservableProperty子类的对象,在这里重写了afterChange方法,会转而调用我们传入的lambda。afterChange方法的调用逻辑则放在ObservableProperty类里面:

public abstract class ObservableProperty<T>(initialValue: T) : ReadWriteProperty<Any?, T> {
    private var value = initialValue

    protected open fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = true

    protected open fun afterChange(property: KProperty<*>, oldValue: T, newValue: T): Unit {}

    public override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value
  }

    public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        val oldValue = this.value
  if (!beforeChange(property, oldValue, value)) {
            return
  }
        this.value = value
        afterChange(property, oldValue, value)
    }
}

主要逻辑在setValue方法里面,我们可以看到,在每次赋值完成之后,都会调用我们的afterChange方法,注意在此之前我们有一个if判断,会终止方法的执行,不过由于我们这儿并没有重写beforeChange方法,所以该方法一直返回trueafterChange在这里一定会被调用。

beforeChange有什么用呢,这就要说到我们的另一个方法了。

var maxLength: String by Delegates.vetoable("init value") { property, oldValue, newValue ->
  newValue.length > oldValue.length }

这里的vetoble方法只有在我们传入的lambda返回true的时候才会执行赋值。

我们来看一下实现:

public inline fun <T> vetoable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean):
        ReadWriteProperty<Any?, T> =
    object : ObservableProperty<T>(initialValue) {
        override fun beforeChange(property: KProperty<*>, oldValue: T, newValue: T): Boolean = onChange(property, oldValue, newValue)
    }

哦哟,这里还是实现的相同的ObservableProperty,这不过这次重写的是beforeChange,也就是说,在这种情况下,调用setValue的时候,我们有可能会不执行赋值操作。

public override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
    val oldValue = this.value
  if (!beforeChange(property, oldValue, value)) {
        return
  }
    this.value = value
    afterChange(property, oldValue, value)
}

当我们传入的lambda返回false时,会停止方法的执行,也就不会赋值了。

这波分析下来,是不是如醍醐灌顶!普通的代理属性加上一些封装却有了类似于观察者模式响应变化的能力。我们也是知道如何实现一个代理属性的,却不一定能做出这样的操作,所以大家还是有时间多读读标准库的源码,总有一些独特的编码示范。

相关文章

  • 什么,属性也能有观察者模式?

    在前面的博文中,我们一起探究了类代理跟代理属性,一起深入了解了它们的实现机制,顺便还讨论了下标准库的玩儿法:laz...

  • Python观察者模式

    观察者模式,被观察物自身属性通知观察者。

  • iOS KVO基础知识

    iOS KVO基础知识 1. 简介 KVO其实就对应设计模式的观察者模式,观察者能够观察其他对象(被观察者)的属性...

  • 常用设计模式

    6.设计模式1> 常用的设计模式代理 观察者 工厂 单例 策略2> 代理属性的内存策略是什么,为什么?3...

  • 观察者模式

    观察者模式 观察者模式的定义 观察者模式(Observer Pattern)也叫做发布订阅模式(Publish/s...

  • iOS设计模式之观察者模式

    观察者模式 1、什么是观察者模式 观察者模式有时又被称为发布(publish)-订阅(Subscribe)模式、模...

  • vue2

    Vue的双向绑定原理(扩展) Object.defineProperty 观察者模式(发布-订阅模式) 计算属性 ...

  • KVO的发现

    1.什么是KVO KVO (key value observer) 观察者模式, 监听对象属性的变化 2.KVO的...

  • KVO

    什么是KVO? KVO是观察者模式,当一个被观察者对象属性发生改变时,观察者会收到通知。 有利于两个类之间的解耦。...

  • 观察者模式(C++实现)

    一、什么是观察者模式 1.1观察者模式的概念 观察者模式(observer pattern)是一种对象行为模式。...

网友评论

    本文标题:什么,属性也能有观察者模式?

    本文链接:https://www.haomeiwen.com/subject/pqoeiqtx.html