Observer 观察者
Observer源码分析
package java.util;
@Deprecated(since="9")
public interface Observer {
//只要改变了 observable 对象就调用此方法。应用程序调用 Observable 对象的 notifyObservers 方法,便向所有该对象的观察者通知此改变。
//参数:
//o - observable 对象。
//注意! arg是被观察对象notifyObservers方法传入的参数
void update(Observable o, Object arg);
}
当被观察对象发生改变时,观察者再调用update方法,它得到消息时并不真实知道被观察对象是否已经发生改变,具体原因在Observable中。个人认为观察者模式中被观察对象将要改变和已经该变应该分开同等对对待,有时在对象改变前接收到信息更重要。
Observable 可观察对象
Observable源码分析
package java.util;
@Deprecated(since="9")
public class Observable {
//是否改变的标志
private boolean changed = false;
//观察者集合,利用Vector同步方法来线程安全
private Vector<Observer> obs;
public Observable() {
obs = new Vector<>();
}
//添加新的观察者集合,重复添加无效,并且不会改变原有顺序
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
//当不传递消息给notifyObservers方法时,仍然通知所有观察者
public void notifyObservers() {
notifyObservers(null);
}
//通过判断changed决定是否发出通知
public void notifyObservers(Object arg) {
Object[] arrLocal;
//保证线程安全
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
//移除所有观察者
public synchronized void deleteObservers() {
obs.removeAllElements();
}
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
//观察者数量
public synchronized int countObservers() {
return obs.size();
}
}
Observable是一个具体实现类,由于java的类单继承性,只继承Observable来实现观察者模式。
代码测试
import java.util.Observable;
import java.util.Observer;
public class TestObserable {
public static void main(String[] args) {
Teacher teacher=new Teacher();
Student s1=new Student("Student 1");
s1.addObserver(teacher);
s1.addObserver(teacher);
s1.setName("Student 2");
}
}
class Teacher implements Observer{
public void update(Observable obs, Object arg) {
System.out.println(((Student)obs).getName()+ "-->"+arg);
}
}
class Student extends Observable {
private String name = "";
public Student(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String newName) {
if (!name.equals(newName)){
name = newName;
setChanged();
notifyObservers(newName);
}
}
}
结果:
Student 2–>Student 2
public void setName(String newName) {
if (!name.equals(newName)){
setChanged();
notifyObservers(newName);
name = newName;
}
}
结果:
Student 1–>Student 2
后续
虽然在jdk9以后已经不建议使用了,但是观察者模式在UI编程中表现优越。在JavaFX得到充分的发展成为javafx.beans的重要接口,并延伸出属性与绑定,可观察对象从单一对象拓展到可观察集合乃至任意类型。
虽然JDK11将javafx移除了,但这也是为了 javafx更长远的发展