public class WeatherD extends Observable{ private double temperature; private double humidity; private double pressure; public double getTemperature() { return temperature; } public double getHumidity() { return humidity; } public double getPressure() { return pressure; } public void setMeasurements(double temp, double humidity, double pressure){ this.temperature = temp; this.humidity = humidity; this.pressure = pressure; double[] args = {temp,humidity,pressure};
//注释一 setChanged(); notifyObservers(args); } }
1.1.1 注释一:setChanged()方法将changed状态置为true,只有changed状态置为true时,在调用notifyObservers()时才会通知观察者。setChanged()方法让你在通知观察者时具备更多的弹性【在某些场景下,并非发布者的数据每一次更新都要通知观察者】。java
public void notifyObservers(Object arg) { /* * a temporary array buffer, used as a snapshot of the state of * current Observers. */ Object[] arrLocal; synchronized (this) { /* We don't want the Observer doing callbacks into * arbitrary code while holding its own Monitor. * The code where we extract each Observable from * the Vector and store the state of the Observer * needs synchronization, but notifying observers * does not (should not). The worst result of any * potential race-condition here is that: * 1) a newly-added Observer will miss a * notification in progress * 2) a recently unregistered Observer will be * wrongly notified when it doesn't care */ if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); }
1.1.2 能够调用clearChanged()将changed状态置为false,调用hasChanged()查看当前的changed的状态。设计模式
public class ObserverB implements Observer { private double temperature; private double humidity; private double pressure; @Override public void update(Observable o, Object arg) { //注释一
//1.push double[] args = (double[]) arg; this.temperature = args[0]; this.humidity = args[1]; this.pressure = args[2]; //2.pull WeatherD d = (WeatherD) o; this.temperature = d.getTemperature(); this.humidity = d.getHumidity(); this.pressure = d.getPressure(); printInfo(); } private void printInfo(){ StringBuilder info = new StringBuilder(); info.append("Current weather date is [temperature : ").append(this.temperature) .append(",humidity : ").append(this.humidity) .append(",pressure : ").append(this.pressure) .append("]."); System.out.println(info.toString()); } }
1.2.1 注释一:Java内置的观察者模式,提供了push(推)和pull(拉)的方式传递数据【push:发布者将全部的数据推送给观察者;pull:观察者经过调用发布者的Getter方法获取须要的数据】 。(一般认为,push的方式更正确)app
须要注意的是,Observable是一个类,若是发布者同时还须要具有另外一个超类的行为,就会陷入两难,毕竟Java不支持多继承,它限制了Observable的复用潜力(而增长复用潜力是模式的原动力)。
ide
【遇到此类状况,你能作的就是自定义一套观察者模式】ui
2. 自定义观察者模式this
自定义观察者模式必须具有四个角色:抽象发布者、具体发布者、抽象观察者、具体观察者。spa
2.1 抽象发布者设计
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObersers(); }
2.2 具体发布者code
经过接口实现发布者,避免了没法继承其它超类的局限。可是,也产生了一个新的问题,即:每建立一个观察者,都必须重写抽象观察者的方法。【固然,能够建立一个中间层,用来实现抽象发布者接口,同时继承其它超类。】server
public class WeatherData implements Subject{ private double temperature; private double humidity; private double pressure; private List<Observer> observers; public WeatherData() { observers = new ArrayList<Observer>(); } public double getTemperature() { return temperature; } public double getHumidity() { return humidity; } public double getPressure() { return pressure; } public void setMeasurements(double temp, double humidity, double pressure){ this.temperature = temp; this.humidity = humidity; this.pressure = pressure; measurementsCharged(); } private void measurementsCharged(){ notifyObersers(); } @Override public void registerObserver(Observer o) { observers.add(o); } @Override public void removeObserver(Observer o) { observers.remove(o); } @Override public void notifyObersers() { for (Observer observer : observers) { observer.update(temperature, humidity, pressure); } } }
2.3 抽象观察者
public interface Observer { public void update(double temp, double humidity, double pressure); }
2.4 具体观察者
public class ObserverA implements Observer { private double temperature; private double humidity; private double pressure; @Override public void update(double temp, double humidity, double pressure) { this.temperature = temp; this.humidity = humidity; this.pressure = pressure; printInfo(); } private void printInfo(){ StringBuilder info = new StringBuilder(); info.append("Current weather date is [temperature : ").append(this.temperature) .append(",humidity : ").append(this.humidity) .append(",pressure : ").append(this.pressure) .append("]."); System.out.println(info.toString()); } }
3. 参考资料
3.1 百度百科:《观察者模式》
3.2 O'Reilly:《Head First设计模式》