1.观察者模式
当我们期望目标值发生变化后其他相关依赖对象可以得到通知并更新,就可以用观察者模式。观察者模式最简单的结构就是一个被观察者和一个实现了响应方法的观察列表。
被观察者:
public class MyObservable {
private int i=0;
private List observableList=new ArrayList();
public void set(int newValue){
i=newValue;
for (BeObservable observable: observableList) {
observable.change(i);
}
}
}
观察者:
class BeObservable{
private String name;
public BeObservable(String name) {
this.name = name;
}
public void change(int newValue){
System.out.println(name+"得到了通知,最新值是"+newValue);
}
}
主函数:
public static void main(String[] args) {
MyObservable myObservable = new MyObservable();
myObservable.observableList.add(new BeObservable("张三"));
myObservable.observableList.add(new BeObservable("李四"));
myObservable.observableList.add(new BeObservable("王五"));
myObservable.set(1);
}
结果:
这样就实现了当一个目标值改变时所有观察者都会得到通知。
2.JavaFx的Simple类
javafx有一些包装的属性类如SimpleIntegerProperty等,这个类可以加监听器当其值发生变化时自动调用监听方法,很实用。
原理就是观察者模式,点开SimpleIntegerProperty的源码分析,肯定就是在set的时候调用了响应方法:
没有set方法,到父类中找:
点set方法:
@Override
public void set(int newValue) {
if (isBound()) {
throw new java.lang.RuntimeException((getBean() != null && getName() != null ?
getBean().getClass().getSimpleName() + "." + getName() + " : ": "") + "A bound value cannot be set.");
}
if (value != newValue) {
value = newValue;
markInvalid();
}
}
所以是调用了markInvalid()方法来通知观察列表,顺着markInvalid()一路点下去,直到点进ExpressionHelper的抽象方法。
在其子类中找到重写后的方法:
@Override
protected void fireValueChangedEvent() {
final T oldValue = currentValue;
currentValue = observable.getValue();
final boolean changed = (currentValue == null)? (oldValue != null) : !currentValue.equals(oldValue);
if (changed) {
try {
listener.changed(observable, oldValue, currentValue);
} catch (Exception e) {
Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
}
}
}
这里的listener.changed(observable, oldValue, currentValue)就是开始分析的观察者模式的响应方法。
3.Kotlin实现简单的监听类
常规javafx的监听实现方法:
SimpleIntegerProperty simpleIntegerProperty = new SimpleIntegerProperty(1); simpleIntegerProperty.addListener((observable, oldValue, newValue) -> { System.out.println("发生了改变"); });
javafx的监听需要重写ChangeListener接口中的change方法,其实写监听器时只是需要change函数,但是java的函数没有类型,所以通过实现接口方法来传递函数。但是kotlin的函数有类型,所以我们用kotlin的函数类型来写一个简单的监听类,当我们改变该类的值时会调用监听方法。
class HigherFunctions(var value: Int) {
var oldValue:Int =0
var changeAction:(oldValue:Int,newValue: Int)->Unit={oldValue,newValue-> println("旧值是$oldValue 新值是$newValue") }
fun set(value: Int){
oldValue=this.value
this.value=value
changeAction(oldValue,value)
}
}
该类的changeAction属性就是一个函数类型属性,作用相当于java监听器中的change()方法,每当这个监听类的值改变的时候都会调用changeAction方法。我们可以对changeAction重新赋值来实现想要的响应方法:
fun main() {
val mySimpleBean =HigherFunctions(0)
mySimpleBean.changeAction={ _,newValue->
println("自定义的方法打印新值$newValue")
}
mySimpleBean.set(5)
mySimpleBean.set(7)
mySimpleBean.set(2)
mySimpleBean.set(1)
}
运行结果:



