javafx观察者模式Observable

对象无效监听器

public interface InvalidationListener {
    public void invalidated(Observable observable);
}

什么是对象无效?

被观察对象正在发生改变,或绑定了其他对象

可观察对象 Observable

public interface Observable {
	void addListener(InvalidationListener listener);
    void removeListener(InvalidationListener listener);
}

addListener方法添加一个当对象无效时的监听器。
removeListener方法则为移除一个监听器。

可观察对象改变监听器 ChangeListener

public interface ChangeListener<T> {
    void changed(ObservableValue<? extends T> observable, T oldValue, T newValue);
}

当对象改变完成后,向所有监听器发出消息。

可观测值对象 ObservableValue

public interface ObservableValue<T> extends Observable {
	void addListener(ChangeListener<? super T> listener);
 	void removeListener(ChangeListener<? super T> listener);
    T getValue();
}

addListener方法添加一个当对象改变的监听器。
removeListener方法则为移除一个监听器

ObservableValue的值可以通过getValue获取。
文档中有说明:

ObservableValue生成两种类型的事件:改变事件和失效事件。更改事件表示值已更改。如果当前值不再有效,将生成一个无效事件。如果ObservableValue支持延迟计算,那么这种区别就变得很重要,因为对于延迟计算的值,在重新计算之前,人们不知道无效值是否真的发生了更改。因此,生成变更事件需要预先评估,而对于预先和延迟的实现可以生成失效事件。

此类的实现应该尽量少生成事件,以避免在事件处理程序中浪费太多时间。当第一个无效化事件发生时,此库中的实现将自己标记为无效。在重新计算值并再次有效之前,它们不会再生成失效事件。

当然这是一个函数式接口,但不建议直接使用。

监听器的存储

实现ObservableValue的方法

    @Override
    public void addListener(InvalidationListener listener) {
        helper = ExpressionHelper.addListener(helper, this, listener);
    }

    @Override
    public void removeListener(InvalidationListener listener) {
        helper = ExpressionHelper.removeListener(helper, listener);
    }

    @Override
    public void addListener(ChangeListener<? super Number> listener) {
        helper = ExpressionHelper.addListener(helper, this, listener);
    }

    @Override
    public void removeListener(ChangeListener<? super Number> listener) {
        helper = ExpressionHelper.removeListener(helper, listener);
    }

ExpressionHelper 有4个静态方法,用于管理可观察对象与监听器。

	public static <T> ExpressionHelper<T> addListener(ExpressionHelper<T> helper, ObservableValue<T> observable, InvalidationListener listener) {
        if ((observable == null) || (listener == null)) {
            throw new NullPointerException();
        }
        observable.getValue(); // validate observable
        return (helper == null)? new SingleInvalidation<T>(observable, listener) : helper.addListener(listener);
    }

    public static <T> ExpressionHelper<T> removeListener(ExpressionHelper<T> helper, InvalidationListener listener) {
        if (listener == null) {
            throw new NullPointerException();
        }
        return (helper == null)? null : helper.removeListener(listener);
    }

    public static <T> ExpressionHelper<T> addListener(ExpressionHelper<T> helper, ObservableValue<T> observable, ChangeListener<? super T> listener) {
        if ((observable == null) || (listener == null)) {
            throw new NullPointerException();
        }
        return (helper == null)? new SingleChange<T>(observable, listener) : helper.addListener(listener);
    }

    public static <T> ExpressionHelper<T> removeListener(ExpressionHelper<T> helper, ChangeListener<? super T> listener) {
        if (listener == null) {
            throw new NullPointerException();
        }
        return (helper == null)? null : helper.removeListener(listener);
    }

    public static <T> void fireValueChangedEvent(ExpressionHelper<T> helper) {
        if (helper != null) {
            helper.fireValueChangedEvent();
        }
    }

只读属性 ReadOnlyProperty

public interface ReadOnlyProperty<T> extends ObservableValue<T> {
   Object getBean();
   String getName();
}

定义所有可读属性通用方法的通用接口。
对象实现此接口,那它将是可读的,即能get到该属性本身。

可写值对象接口 WritableValue

public interface WritableValue<T> {
    T getValue();
    void setValue(T value);
}

WritableValue是一个包含可读取和设置的值的接口

属性接口 Property

public interface Property<T> extends ReadOnlyProperty<T>, WritableValue<T> {
    void bind(ObservableValue<? extends T> observable);
    void unbind();
    boolean isBound();
    void bindBidirectional(Property<T> other);
    void unbindBidirectional(Property<T> other);
}

bind 为此属性创建单向绑定。
unbind 删除此属性的单向绑定。
isBound 可以用于检查是否绑定了属性。
bindBidirectional 在这个属性和另一个属性之间创建双向绑定。双向绑定独立于单向绑定存在。因此,可以向具有双向绑定的属性添加单向绑定,反之亦然。然而,这种做法是不可取的。一个属性可以有多个双向绑定。
unbindBidirectional 删除此属性与另一个属性之间的双向绑定

可观察属性对象

以SimpleIntegerProperty为例

可写数值类型接口

public interface WritableNumberValue extends WritableValue<Number> {
}

WritableValue为可写值对象接口,类型指定Number
意味着WritableNumberValue为可写数值类型接口

可写整型值类型接口

WritableIntegerValue 指明了方法类型为int

public interface WritableIntegerValue extends WritableNumberValue {
    int get();
    void set(int value);
    void setValue(Number value);
}

只读整型属性抽象类

ReadOnlyIntegerProperty 继承ReadOnlyProperty 将具有读取属性
IntegerExpression 定义了一些基本方法,比如用于绑定的方法。

public abstract class ReadOnlyIntegerProperty extends IntegerExpression
        implements ReadOnlyProperty<Number> {
        ...
}

整型属性抽象类

此类定义了一个整型属性具有的读写操作和绑定操作。

public abstract class IntegerProperty extends ReadOnlyIntegerProperty implements
        Property<Number>, WritableIntegerValue {
        ...
}

整型属性基类

public abstract class IntegerPropertyBase extends IntegerProperty {...}

在IntegerPropertyBase 中实现了 ObservableValue 的 5个方法

简单整型属性类

public class SimpleIntegerProperty extends IntegerPropertyBase {

    private static final Object DEFAULT_BEAN = null;
    private static final String DEFAULT_NAME = "";

    private final Object bean;
    private final String name;
    public Object getBean() {
        return bean;
    }
    public String getName() {
        return name;
    }
    public SimpleIntegerProperty() {
        this(DEFAULT_BEAN, DEFAULT_NAME);
    }
    public SimpleIntegerProperty(int initialValue) {
        this(DEFAULT_BEAN, DEFAULT_NAME, initialValue);
    }
    public SimpleIntegerProperty(Object bean, String name) {
        this.bean = bean;
        this.name = (name == null) ? DEFAULT_NAME : name;
    }
    public SimpleIntegerProperty(Object bean, String name, int initialValue) {
        super(initialValue);
        this.bean = bean;
        this.name = (name == null) ? DEFAULT_NAME : name;
    }
}

getBean和getName为实现ReadOnlyProperty接口的方法
其余都是构造方法,都是围绕着bean,name,value属性
bean为一个对象,可以为空
name为SimpleIntegerProperty的名字,默认为DEFAULT_NAME。
name为SimpleIntegerProperty的值,默认为0。

测试

	  public static void main(String[] args) {
		  SimpleIntegerProperty a=new SimpleIntegerProperty(null,"a",2);
		  System.out.println(a);
	  }

输出 :
IntegerProperty [name: a, value: 2]

添加监听器

public static void main(String[] args) {
		  SimpleIntegerProperty a=new SimpleIntegerProperty(null,"a",2);
		  System.out.println(a);
		 
		  a.addListener(new InvalidationListener() {
		      public void invalidated(Observable o) {
		        System.out.println("绑定现在无效");
		      }
		  });
		  a.addListener(new ChangeListener<Number>() {
			  public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
				  System.out.println("observable: "+observable);
				  System.out.println("oldValue :"+oldValue);
				  System.out.println("newValue :"+newValue);
			  }
		  });
		  a.set(3);
		  System.out.println(a);

输出 :
IntegerProperty [name: a, value: 2]
绑定现在无效
observable: IntegerProperty [name: a, value: 3]
oldValue :2
newValue :3
IntegerProperty [name: a, value: 3]

set方法调用了markInvalid()发出消息。

单向绑定

a 绑定b后,若改变a的值将导致异常。

	  public static void main(String[] args) throws InterruptedException {
		  SimpleIntegerProperty a=new SimpleIntegerProperty(null,"a",2);
		  System.out.println(a);
		  SimpleIntegerProperty b=new SimpleIntegerProperty(null,"b",1);
		  System.out.println(b);

		  a.addListener(new InvalidationListener() {
		      public void invalidated(Observable o) {
		        System.out.println("绑定现在无效");
		      }
		  });
		  a.addListener(new ChangeListener<Number>() {
			  public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
				  System.out.println("observable: "+observable);
				  System.out.println("oldValue :"+oldValue);
				  System.out.println("newValue :"+newValue);
			  }
		  });
		  a.bind(b);
		  System.out.println(a);
		  
		  b.set(3);
		  System.out.println(b);
		  System.out.println(a);
	}

输出 :
IntegerProperty [name: a, value: 2]
IntegerProperty [name: b, value: 1]
绑定现在无效
observable: IntegerProperty [name: a, bound, value: 1]
oldValue :2
newValue :1
IntegerProperty [name: a, bound, value: 1]
绑定现在无效
observable: IntegerProperty [name: a, bound, value: 3]
oldValue :1
newValue :3
IntegerProperty [name: b, value: 3]
IntegerProperty [name: a, bound, value: 3]

解除单向绑定

方法unbind()

双向绑定

	  public static void main(String[] args) throws InterruptedException {
		  SimpleIntegerProperty a=new SimpleIntegerProperty(null,"a",2);
		  System.out.println(a);
		  SimpleIntegerProperty b=new SimpleIntegerProperty(null,"b",1);
		  System.out.println(b);

		  a.addListener(new InvalidationListener() {
		      public void invalidated(Observable o) {
		        System.out.println("绑定现在无效");
		      }
		  });
		  a.addListener(new ChangeListener<Number>() {
			  public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
				  System.out.println("observable: "+observable);
				  System.out.println("oldValue :"+oldValue);
				  System.out.println("newValue :"+newValue);
			  }
		  });
		  a.bindBidirectional(b);
		  System.out.println(a);
		  
		  a.set(3);
		  System.out.println(a);
		  System.out.println(b);
		  
		  b.set(5);
		  System.out.println(a);
		  System.out.println(b);
	}

输出 :
IntegerProperty [name: a, value: 2]
IntegerProperty [name: b, value: 1]
绑定现在无效
observable: IntegerProperty [name: a, value: 1]
oldValue :2
newValue :1
IntegerProperty [name: a, value: 1]
绑定现在无效
observable: IntegerProperty [name: a, value: 3]
oldValue :1
newValue :3
IntegerProperty [name: a, value: 3]
IntegerProperty [name: b, value: 3]
绑定现在无效
observable: IntegerProperty [name: a, value: 5]
oldValue :3
newValue :5
IntegerProperty [name: a, value: 5]
IntegerProperty [name: b, value: 5]

解除双向绑定

方法 unbindBidirectional(other)

猜你喜欢

转载自blog.csdn.net/qq_39464369/article/details/89789959