引子,如圖:
劉鵬經理在王芳姑娘身上安裝了監視器,那麼能不能在代碼裏給變量安裝監視器呢?比如實現這樣的功能:
int i = 100
watch(i, log(old, new) { print old, new}) 給變量I 安裝一個監視器
i += 100 當i 變化時候,會調用log函數。
怎麼實現呢?函數式語言貌似不倡導可變變量,那麼用支持可變對象的Scala試試看吧。
我首先想到的就是 SET屬性, 然後在屬性裏調用註冊好的函數,代碼如下:
/*
你。。你在我身上安裝了監視器 代碼版本
*/
class Watch[T] (var value: T) {
type F = (T, T) => Unit
val dict = new scala.collection.mutable.HashMap[String, F]()
def setValue(t: T) {
for ((_,f1) <- dict) {
f1(value, t)
}
value = t
}
def addWatch(k:String)(f:F) {
dict(k) = f
}
def removeWatch(k:String){
dict.remove(k)
}
}
object Watch {
def apply[T](t: T) = new Watch(t)
}
object Hi {
def main(args: Array[String]) {
//聲明一個watch變量
val w1 = new Watch("Hello")
//添加一個監視器
w1.addWatch("key1") {
(oldValue: String , newValue: String) =>
println(s"w1 Old Value: $oldValue => New Value: $newValue")
}
//通過setValue改變值
w1.setValue("123")
var w2 = Watch(111111)
w2.addWatch("key1") {
(oldValue: Int , newValue: Int) =>
println(s"w2 Old Value: $oldValue => New Value: $newValue")
}
w2.setValue(2222222)
//移除監視器
w2.removeWatch("key1")
//下面的沒有監視器了
w2.setValue(3333333)
implicit def i2Watch(a: Int) = Watch(a)
var i = 10;
i.addWatch("key1"){
(oldValue: Int , newValue: Int) =>
println(s"w2 Old Value: $oldValue => New Value: $newValue")
}
//這裏每次都會 重新 new 一個Watch,所以不起作用的
//
i.setValue(100);
}
}
結果如下:
不知道還有沒有更優雅的實現方式呢。