设计模式之观察者模式

        观察者(Observer)设计模式定义了对象间的一种一对多的组合关系(一是发布者,多是观察者),以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新【即:信息即时同步】。为了实现松耦合,观察者和发布者之间的互动关系不是类之间的直接调用[对于观察者,发布者只需要知道其实现了某个接口(Oberver接口),至于观察者到底是谁,发布者并不在乎]。
 
         本质上, 观测者模式 = 发布者 + 观察者
 
        JDK提供了内置的观察者模式【java.util.Observable,java.util.Observer】,用户只需要定义具体的发布者和观察者。
 
1. JDK内置的观察者模式
    1.1 发布者 : 继承Obsrevable类,是数据的拥有者。当数据发生更新时,发布者会通知依赖的观察者
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()方法让你在通知观察者时具有更多的弹性【在某些场景下,并不是发布者的数据每一次更新都要通知观察者】。

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的状态。

    1.2  观察者 :实现Observer接口,是数据的处理者。从发布者获取数据后,观察者会对数据进行处理
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的方式更正确)

 

               需要注意的是,Observable是一个类,如果发布者同时还需要具备另一个超类的行为,就会陷入两难,毕竟Java不支持多继承,它限制了Observable的复用潜力(而增加复用潜力是模式的原动力)。

               【遇到此类情况,你能做的就是自定义一套观察者模式】

 

2. 自定义观察者模式

           自定义观察者模式必须具备四个角色:抽象发布者、具体发布者、抽象观察者、具体观察者。

    2.1 抽象发布者

public interface Subject {

    public void registerObserver(Observer o);
    
    public void removeObserver(Observer o);
    
    public void notifyObersers();
}

    2.2 具体发布者

        通过接口实现发布者,避免了无法继承其它超类的局限。但是,也产生了一个新的问题,即:每创建一个观察者,都必须重写抽象观察者的方法。【当然,可以创建一个中间层,用来实现抽象发布者接口,同时继承其它超类。】

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设计模式》

posted @ 2019-01-25 17:04  blue星空  阅读(205)  评论(0编辑  收藏  举报