koitlin 行為模式---觀察者模式
簡單來說悯森,需要滿足的兩件事:
- 訂閱者盅蝗,添加或者刪除 觀察者的監(jiān)聽
- 發(fā)布者狀態(tài)改變的時候卧秘,通知觀察者呢袱,觀察者執(zhí)行相應(yīng)的響應(yīng)邏輯
java 自身標準提供了java.util.Observable 類和java.util.Observer接口來幫助實現(xiàn)觀察者模式。實現(xiàn)一個動態(tài)更新價格的例子翅敌;
import java.util.*
class StockUpdate: Observable() {
val observers = mutableSetOf<Observer>();
fun setStockChanched(price:Int){
this.observers.forEach { it.update(this,price) }
}
}
class StockDisplay:Observer{
override fun update(o: Observable?, price: Any?) {
if(o is StockUpdate){
println("The latest stock price is $price")
}
}
}
fun main() {
val su = StockUpdate()
val sd = StockDisplay()
su.observers.add(sd)
su.setStockChanched(200)
}
Observable
Kotlin 的標準庫引入了可被觀察者委托屬性羞福,也可以利用來實現(xiàn)同樣的場景
import kotlin.properties.Delegates
interface StockUpdateListener{
fun onRise(price:Int)
fun onFall(price:Int)
}
class StockDisplay2:StockUpdateListener{
override fun onRise(price: Int) {
println("The latest stock prise has risen to $price")
}
override fun onFall(price: Int) {
println("The latest stock prise has fall to $price")
}
}
class StockUpdate2{
var listeners = mutableSetOf<StockUpdateListener>()
var price:Int by Delegates.observable(0){_,old,new->
listeners.forEach {
if(new > old) it.onRise(price) else it.onFall(price)
}
}
}
fun main() {
val su = StockUpdate2()
val sd = StockDisplay2()
su.listeners.add(sd)
su.price = 100
su.price = 98
這里我們添加了功能,價格上漲和下跌觀察蚯涮。java.util.Observer 的接口類只能復(fù)寫update方法來寫相應(yīng)邏輯治专,也就是說卖陵,如果存在多種不同的邏輯響應(yīng),我們也必須通過在改方法中進行區(qū)分實現(xiàn)张峰。這回讓訂閱者顯得臃腫泪蔫。如果我們把發(fā)布者的事件推送看成一個第三方服務(wù),那么他提供的API接口只有一個update喘批,API調(diào)用者必須承擔(dān)更多的職能撩荣。
使用Delegates.observable() 的方案更加靈活。提供了三個參數(shù)饶深,一次代表:委托屬性的元數(shù)據(jù)KProperty對象餐曹,舊值以及新值。通過額外定義一個StockUpdateListener接口敌厘,上漲和下跌的不同邏輯響應(yīng)封裝成了接口方法台猴,從而,StockDisplay 中實現(xiàn)該接口的onRise和onFall 方法實現(xiàn)了解耦
Vetoable
我們有時候不希望監(jiān)控的值隨意更改俱两,可能希望對某些改值的情況進行否決饱狂。Kotlin標準庫除了observable這個委托屬性之外,還提供了另外一個屬性宪彩,vetoable休讳,提供了功能,在被賦值前進行截獲毯焕,判斷是否接受衍腥。
var value:Int by Delegates.vetoable(0){
prop,old,new->
new > 0
}
>>>>
value = 1
println(value)
value = -1
println(value)
>>>>
1
1
初始值0,視圖value更改為-1的時候結(jié)果仍未舊值1