观察者模式

观察者模式:

  当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象状态被修改时,其他依赖者都会收到通知。观察者模式属于行为型模式。

例子:

  如下图所示,此例子有三个部分:气象站(获取实际气象数据的物理装置)、WeatherData对象(追踪来自气象站的数据,并更新布告板)、布告板(显示目前天气状况给用户看)。

当WeatherData获得最新天气数据时,三种布告板实时更新。

 

 

 

 设计气象站:

 

 

 

代码实现:

三个需要实现的接口:

public interface Subject {
    /**
     * 注册观察者
     * @param o
     */
    public void registerObserver(Observer o);

    /**
     * 移除观察者
     * @param o
     */
    public void removeObserver(Observer o);

    /**
     * 状态改变时,通知所有观察者
     */
    public void notifyObserver();
}

public interface Observer {
    public void update(float temp, float humidity, float pressure);
}

public interface DisplayElement {

    /**
     * 显示方法
     */
    public void display();
}

WeatherData类实现:

public class WeatherData implements Subject {
    private ArrayList observers;
    /**
     * 温度
     */
    private float temperature;
    /**
     * 湿度
     */
    private float humidity;
    /**
     * 气压
     */
    private float pressure;

    public WeatherData(){
        observers = new ArrayList();
    }

    @Override
    public void registerObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        int i = observers.indexOf(o);
        if(i >= 0){
            observers.remove(i);
        }
    }

    @Override
    public void notifyObserver() {
        for(int i = 0; i < observers.size(); i++){
            Observer observer = (Observer) observers.get(i);
            observer.update(temperature, humidity, pressure);
        }
    }

    public void measurementsChanged(){
        notifyObserver();
    }

    public void setMeasurements(float temperature, float humidity, float pressure){
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
}

布告栏类:

 1 public class CurrentConditionDisplay implements Observer, DisplayElement{
 2     private float temperature;
 3     private float humidity;
 4     private Subject weatherData;
 5 
 6     public CurrentConditionDisplay(Subject wd){
 7         this.weatherData = wd;
 8         weatherData.registerObserver(this);
 9     }
10 
11     @Override
12     public void update(float temp, float humidity, float pressure) {
13         this.temperature = temp;
14         this.humidity = humidity;
15         display();
16     }
17 
18     @Override
19     public void display() {
20         System.out.println("current conditions(目前天气状况): " + temperature
21         + "F degrees and " + humidity + "% humidity");
22     }
23 }

其他两个布告栏类似

测试类:

 1 public class WeatherStationMain {
 2 
 3     public static void main(String[] args){
 4         WeatherData weatherData = new WeatherData();
 5         CurrentConditionDisplay ccd = new CurrentConditionDisplay(weatherData);
 6         StatisticsDisplay sd = new StatisticsDisplay(weatherData);
 7         ForecastDisplay fd = new ForecastDisplay(weatherData);
 8 
 9         weatherData.setMeasurements(80, 70, 20.4f);
10         System.out.println();
11         weatherData.setMeasurements(60, 83, 30.7f);
12     }
13 }

自定义的observer已经完成,java提供了自己的观察者模式。

 

Java内置观察者模式:

1、如何把对象变成观察者

  实现观察者接口(java.uitl.Observer),然后调用Observable对象的addObserver()方法。不想在当观察者了,调用deleteObserver()方法。

2、观察者如何发送通知

  首先,需要实现java.util.Observable接口,产生“可观察者”类,然后,需要两个步骤:

  (1)先调用setChanged()方法,标记状态已经改变的事实。

  (2)然后调用两种notifyObservers()方法中的一个:拉方式:notifyObservers() 、  推方式:notifyObservers(Object arg)

3、观察者如何接收通知

  实现观察者接口(java.uitl.Observer),实现更新方法update(Observable o, Object arg),arg参数内容为notifyObservers(Object arg)推送的数据。

Java内置观察者模式具体实现代码可参考我的github上的实现:https://github.com/oshua/design-pattern

 

注意:java内置模式的缺点,Observable是一个类:如果想同时具有Observable和另一个超类的行为,不能实现,因为Java不支持多重继承,这就限制了Observable的复用潜力。

 

  

  

 

posted @ 2019-09-24 10:43  oush  阅读(285)  评论(0编辑  收藏  举报