Android开发中的基于观察者模式实现的设计仍是不少的,好比rxjava、LiveData...常见的按钮点击事件html
观察者模式定义可一对多的依赖关系,让多个观察者同时监听某一个对象,当这个主体对象在状态上发生变化时,会通知全部观察者对象 ,使他们能自动更新本身,叫法也有不少,发布-订阅(Publish-Subscribe)、模型-视图(Model-View)等等java
Java对于观察者模式在java.util包中提供了Observer接口和Observable抽象类。注册,删除,通知观察者等功能已内置。kotlin一样支持使用Java中提供的观察者模式bash
例如电商项目中的动态更新价格markdown
// 被观察者 class PriceSubject : Observable() { // 定义一组观察者对象 private val observers = mutableSetOf<Observer>() // 订阅 fun subject(ob: Observer) { observers.add(ob) } // 解除订阅 fun UnSubject(ob: Observer) { observers.remove(ob) } // 价格赋值 fun setPrice(price:Int ){ notify(price) } //更新数据 private fun <T : Any?> notify(msg: T) { for (ob in observers) { ob.update(this,msg) } } } // 观察者 class PriceOb(private val channel:String):Observer{ override fun update(o: Observable?, price: Any?) { if (o is PriceSubject){ print("接收赋值-观察者:$channel - 价格:$price\n") } } } class PriceOb1 :Observer by PriceOb("第三方") fun main(args: Array<String>) { PriceSubject().apply { // 订阅 subject(PriceOb("自营")) subject(PriceOb1()) setPrice(100) } } 复制代码
接收赋值-观察者:自营 - 价格:100
接收赋值-观察者:第三方 - 价格:100
复制代码
kotlin中的委托属性官方文档 其中咱们须要的是app
可观察属性(observable properties): 监听器会收到有关此属性变动的通知ide
inline fun <T> observable(
initialValue: T,
crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit
): ReadWriteProperty<Any?, T>
复制代码
如果咱们赋予价格属性更多定义,咱们须要发布者对外提供一个API接口而不是在实现Observer接口的类中区分不一样的逻辑。oop
Delegates.observable()
中提供了表明委托属性三个参数:元数据property: KProperty<*>
对象,新旧值。this
// 观察者 interface PriceChangedListener { // 定义一系列事件 // fun onNormalPrice(price: Price) // 秒杀价 fun onSpikePrice(price: Price) // 预购价 fun onAdvancePrice(price: Price) // 会员价 fun onVIPPrice(price: Price) // } class PriceObserver : PriceChangedListener { override fun onNormalPrice(price: Price) { print("常规价${price.newPrice}") } override fun onSpikePrice(price: Price) { print("秒杀价${price.newPrice}") } override fun onAdvancePrice(price: Price) { print("预购价${price.newPrice}") } override fun onVIPPrice(price: Price) { print("会员价${price.newPrice}") } } data class Price(val newPrice: Int, //新价格 val oldPrice: Int, //旧价格 val type: Int, //价格属性类型 val discount: Boolean //是否能抵用折扣 ) // 被观察者 class PriceSubject { // 观察者对象 private var listeners = mutableSetOf<PriceChangedListener>() fun subject(ob: PriceChangedListener) { listeners.add(ob) } fun unSubject(ob: PriceChangedListener) { listeners.remove(ob) } var price: Price by Delegates.observable(Price(0, 0, 0, false)) { property, oldValue, newValue -> listeners.forEach { when (newValue.type) { 0 -> it.onNormalPrice(newValue) 1 -> it.onSpikePrice(newValue) 2 -> it.onAdvancePrice(newValue) 3 -> it.onVIPPrice(newValue) } } } } fun main(args: Array<String>) { PriceSubject().apply { subject(PriceObserver()) price = Price(199, 0, 0, false) price = Price(99, 100, 3, false) } } 复制代码
inline fun <T> vetoable(
initialValue: T,
crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean
): ReadWriteProperty<Any?, T>
复制代码
在观察者模式中,若是咱们不想被观察的值被任意的修改,能够利用Vetoable在新的值被赋值生效以前进行截获,而后根据相关业务逻辑处理它。spa
var price: Price by Delegates.vetoable(Price(0, 0, 0, false)) { property, oldValue, newValue -> listeners.forEach { when (newValue.type) { 0 -> it.onNormalPrice(newValue) 1 -> it.onSpikePrice(newValue) 2 -> it.onAdvancePrice(newValue) 3 -> it.onVIPPrice(newValue) } } // 添加自定义规则 if (newValue.type==3&&newValue.oldPrice < newValue.newPrice) true else throw IllegalArgumentException("会员价格不合理") } 复制代码