Android開發(fā)中的基于觀察者模式實(shí)現(xiàn)的設(shè)計(jì)還是很多的,比如rxjava镣奋、LiveData...常見的按鈕點(diǎn)擊事件
- Button ---> 被觀察者
- OnClickListener ---> 觀察者
- setOnClickListener() ---> 訂閱
- OnClick() ---> 事件
觀察者模式定義可一對(duì)多的依賴關(guān)系后豫,讓多個(gè)觀察者同時(shí)監(jiān)聽某一個(gè)對(duì)象悉尾,當(dāng)這個(gè)主體對(duì)象在狀態(tài)上發(fā)生變化時(shí),會(huì)通知所有觀察者對(duì)象 挫酿,使他們能自動(dòng)更新自己构眯,叫法也有很多,發(fā)布-訂閱(Publish-Subscribe)早龟、模型-視圖(Model-View)等等
Java對(duì)于觀察者模式在java.util包中提供了Observer接口和Observable抽象類惫霸。注冊(cè),刪除,通知觀察者等功能已內(nèi)置。kotlin同樣支持使用Java中提供的觀察者模式
例如電商項(xiàng)目中的動(dòng)態(tài)更新價(jià)格
// 被觀察者
class PriceSubject : Observable() {
// 定義一組觀察者對(duì)象
private val observers = mutableSetOf<Observer>()
// 訂閱
fun subject(ob: Observer) {
observers.add(ob)
}
// 解除訂閱
fun UnSubject(ob: Observer) {
observers.remove(ob)
}
// 價(jià)格賦值
fun setPrice(price:Int ){
notify(price)
}
//更新數(shù)據(jù)
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 - 價(jià)格:$price\n")
}
}
}
class PriceOb1 :Observer by PriceOb("第三方")
fun main(args: Array<String>) {
PriceSubject().apply {
// 訂閱
subject(PriceOb("自營"))
subject(PriceOb1())
setPrice(100)
}
}
接收賦值-觀察者:自營 - 價(jià)格:100
接收賦值-觀察者:第三方 - 價(jià)格:100
委托屬性
kotlin中的委托屬性官方文檔
其中我們需要的是
可觀察屬性(observable properties): 監(jiān)聽器會(huì)收到有關(guān)此屬性變更的通知
inline fun <T> observable(
initialValue: T,
crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit
): ReadWriteProperty<Any?, T>
若是我們賦予價(jià)格屬性更多定義葱弟,我們需要發(fā)布者對(duì)外提供一個(gè)API接口而不是在實(shí)現(xiàn)Observer接口的類中區(qū)分不同的邏輯壹店。
Delegates.observable()
中提供了代表委托屬性三個(gè)參數(shù):元數(shù)據(jù)property: KProperty<*>
對(duì)象,新舊值芝加。
// 觀察者
interface PriceChangedListener {
// 定義一系列事件
//
fun onNormalPrice(price: Price)
// 秒殺價(jià)
fun onSpikePrice(price: Price)
// 預(yù)購價(jià)
fun onAdvancePrice(price: Price)
// 會(huì)員價(jià)
fun onVIPPrice(price: Price)
//
}
class PriceObserver : PriceChangedListener {
override fun onNormalPrice(price: Price) {
print("常規(guī)價(jià)${price.newPrice}")
}
override fun onSpikePrice(price: Price) {
print("秒殺價(jià)${price.newPrice}")
}
override fun onAdvancePrice(price: Price) {
print("預(yù)購價(jià)${price.newPrice}")
}
override fun onVIPPrice(price: Price) {
print("會(huì)員價(jià)${price.newPrice}")
}
}
data class Price(val newPrice: Int, //新價(jià)格
val oldPrice: Int, //舊價(jià)格
val type: Int, //價(jià)格屬性類型
val discount: Boolean //是否能抵用折扣
)
// 被觀察者
class PriceSubject {
// 觀察者對(duì)象
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)
}
}
Vetoable
inline fun <T> vetoable(
initialValue: T,
crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Boolean
): ReadWriteProperty<Any?, T>
在觀察者模式中硅卢,如果我們不想被觀察的值被任意的修改,可以利用Vetoable在新的值被賦值生效之前進(jìn)行截獲,然后根據(jù)相關(guān)業(yè)務(wù)邏輯處理它将塑。
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)
}
}
// 添加自定義規(guī)則
if (newValue.type==3&&newValue.oldPrice < newValue.newPrice)
true else throw IllegalArgumentException("會(huì)員價(jià)格不合理")
}