设计模式整理_观察者模式

Posted 大胡龙的小圈子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式整理_观察者模式相关的知识,希望对你有一定的参考价值。

  观察者模式定义了对象之间的一对多的依赖,这样一来,当一个对象的状态发生改变的时候,它的所有依赖者都会收到通知,并且进行更新.

  被观测的对象称为主题(Subject),观察被观测的对象的对象称为观察者(Observer).

  现实中的观察者模式:例如报纸的订阅.不同人(Observer)向报社(Subject)订购报纸,当报社出品了新的报纸的时候,将会通知它的订阅者,送报纸.中途订阅者可以取消订阅,此时报社就不再给他报纸.但是只要报社一直存在,就可以有人订阅报纸.

  在JavaGUI中,就有观察者模式的体现,例如Button按钮的实现.JButton会有增加和删除Listener(倾听者)的方法.

  观察者模式提供了一种对象设计,让主题和观察者之间松耦合.关于观察者的一切,主题只知道观察者实现了某个接口,主题不需要知道观察者的实现类是谁,做了什么或其他任何细节.在运行时候,我们可以用新的观察者来取代现有的观察者,主题不会收到任何影响.新类型观察者出现,主题也不需要作出修改,只需要在新的类里面实现了观察者接口,然后注册为观察者即可.改变主题或观察者的任意一方,并不会影响另一方,因为两者是松耦合的,所有可以自由改变.

  示例:

  

import java.util.ArrayList;
/*
 * 演示主题.
 * */
public interface Subject {
    public void registerObserver(Observer o);        //注册观察者
    public void removeObserver(Observer o);            //移除观察者
    public void notifyObservers();        //主题状态发生变化的时候,通知观察者。
}
class WeatherData implements Subject {
    private ArrayList<Observer> observers;    //观察者队列,不需要知道观察者的具体实现细节。
    private float temperature;
    private float humidity;
    private float pressure;
    
    public WeatherData() {
        observers=new ArrayList<Observer>();
    }
    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
        System.out.println("注册一项观察者.");
    }

    @Override
    public void removeObserver(Observer o) {
        int i=observers.indexOf(o);
        if(i>=0)
        observers.remove(o);
        System.out.println("移除一项观察者.");
    }

    @Override
    public void notifyObservers() {
        for (int i = 0; i < observers.size(); i++) {
            /*
             * 这里由于每个观察者都实现了Observer接口,因此我们知道如何去通知观察者来做出更新动作。
             * */
            observers.get(i).update(temperature, humidity, pressure);
        }
    }
    
    public void measurementsChanged() /*当状态发生改变的时候,需要通知观察者*/{
        notifyObservers();
    }
    
    public void setMeasurements(float temperature,float humidity,float pressure) {
        this.temperature=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        measurementsChanged();
    }
}
/*
 * 演示观察者
 * */
public interface Observer {
    public void update(float temp,float humidity,float pressure);
}
class CurrentConditionObserver implements Observer/*实现了观察者接口,可以获得改变。*/ {
    private float temperature;
    private float humidity;
    private Subject weatherData;
    
    public CurrentConditionObserver(Subject weatherData) {
        this.weatherData = weatherData;    //构造器需要WeatherData对象作为注册时使用。
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temp, float humidity, float pressure) {
        this.temperature=temp;
        this.humidity=humidity;
        display();
    }

    public void display() {
        System.out.println("Current Conditions:"+temperature+
                " F degrees and "+humidity+"% humidity");
    }
    
}
/*
 * 测试主题和观察者.这里只用了一个观察者.
 * */
public class Test {
    public static void main(String[] args) {
        WeatherData data=new WeatherData();
        CurrentConditionObserver obs=new CurrentConditionObserver(data);
        data.setMeasurements(80, 65, 30);
        data.setMeasurements(82, 70, 29.2f);
        data.setMeasurements(84, 0, 29.2f);
        data.removeObserver(obs);
    }
}

  类图如下:

  实际上Java为我们提供了观察者和被观察者的便捷实现,即Observable类和Observer接口,被观察者只需要继承Observable类即可实现被观察的功能,而观察者只需要实现Observable接口即可.下面是示例,利用Java给定的观察者和被观察者对象,对代码做出了调整:

  

/*
 * 演示主题.
 * */
import java.util.Observable;

class WeatherData extends Observable {
    private float temperature;
    private float humidity;
    private float pressure;
    //不再需要继承观察者而建立数据结构了.实际上Observable类已经为我们做好了这件事情.
    public WeatherData() {
    }
    public float getTemperature() {
        return temperature;
    }
    
    
    public float getHumidity() {
        return humidity;
    }
    
    
    public float getPressure() {
        return pressure;
    }
    
    
    public void measurementsChanged() /*当状态发生改变的时候,需要通知观察者*/{
        setChanged();    //调用notifyObservers方法之前,需要先调用setChanged来指示状态改变
        notifyObservers();
    }
    
    public void setMeasurements(float temperature,float humidity,float pressure) {
        this.temperature=temperature;
        this.humidity=humidity;
        this.pressure=pressure;
        measurementsChanged();
    }
}
import java.util.Observable;
import java.util.Observer;

/*
 * 演示观察者
 * */
class CurrentConditionObserver implements Observer/*实现了观察者接口,可以获得改变。*/ {
    private float temperature;
    private float humidity;
    Observable obs;
    
    public CurrentConditionObserver(Observable weatherData) {
        this.obs = weatherData;    //构造器需要Observable对象作为注册时使用。
        weatherData.addObserver(this);
    }

    public void display() {
        System.out.println("Current Conditions:"+temperature+
                " F degrees and "+humidity+"% humidity");
    }

    @Override
    public void update(Observable o, Object arg) {    //覆盖update方法,从Observable对象中获取值
        if(o instanceof WeatherData) {
            WeatherData data=(WeatherData) o;
            this.temperature=data.getTemperature();
            this.humidity=data.getHumidity();
            display();
        }
    }
    
}

  但是实际上Java提供的这种机制是有缺陷的,因为Observable是一个类,因此只能继承来实现,这要求被观察的对象没有父类,另外一方面,也违反了设计模式当中的"多用组合,少用继承的原则,因此,有必要的时候,还是需要自己来实现观察者对象和被观察者对象.

  

以上是关于设计模式整理_观察者模式的主要内容,如果未能解决你的问题,请参考以下文章

扎实基础_设计模式_行为型_观察者模式(项目实战,使用委托注册事情,消除多重判断)

扎实基础_设计模式_行为型_观察者模式(项目实战,使用委托注册事情,消除多重判断)

观察者模式

高级 Java 面试通关知识点整理!

23种设计模式汇总整理

23种设计模式汇总整理(转)