菜鸟柳--23种设计模式初学记录笔记(四)观察者模式

感觉上一章写的太磨叽,还没说重点,这一张我就直接把观察者模式写出来,并对java中的涉及到的Observable类和Observe接

口进行说明:

观察者模式四个组成部分:

Subject主题----------ConcreteSubject具体的主题

Observer观察者(抽象的观察主题的对象)----------ConcreteObserver具体的观察者


(在java中java.util.Observer接口就是封装好的Subject主题,java.util.Observable类是封装好的观察者对象)


观察者模式起到的作用是,当主题发生改变,观察主体的对象们都会获得通知,这种通知的形式都是主题主动推给观察的人,而不是观察者过来恳求主题给他们的。

下边的例子是一个气象站(主题),监测这环境的温度、湿度、气压等一系列资料,一旦有变动,布告栏(观察者们)会实时的更改他们展示给大众的数据。

public interface Subject {  
    public void registerObserver(Observer o);  //添加观察者到主题内部的观察者集合中(每次有改变,主题就到自己的这个集合中,遍历调用方法告诉观察者们)
    public void removeObserver(Observer o);  //删除集合中的某个观察者
    public void notifyObservers(); //通知所有的观察者(这一步就是前边说的遍历通知)
}  
public interface Observer {  
    public void update(float temp, float humidity, float pressure);  //这个方法是主题变化时会调用所有注册的观察者的此方法,来进行数据推送
}  
public class WeatherData implements Subject {  
    private ArrayList observers;  //这就是那个记录着所有观察者的集合,主题手里的小本本,记录了所有要通知的人
    //temperature、humidity、pressure就是WeatherData的“状态”  
    private float temperature;  
    private float humidity;  
    private float pressure;  
      
    public WeatherData() {  
        observers = new ArrayList();  
    }  
      
    public void registerObserver(Observer o) {  
        observers.add(o);  
    }  
      
    public void removeObserver(Observer o) {  
        int i = observers.indexOf(o);  
        if (i >= 0) {  
            observers.remove(i);  
        }  
    }  
      
    public void notifyObservers() {  
        for (int i = 0; i < observers.size(); i++) {  
            Observer observer = (Observer)observers.get(i);  
            observer.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 float getTemperature() {  
        return temperature;  
    }  
      
    public float getHumidity() {  
        return humidity;  
    }  
      
    public float getPressure() {  
        return pressure;  
    }  
}  
public interface DisplayElement {  //这个接口是布告板的东西,里面的展示功能是让不同的布告板去实现的,跟模式没什么关系
    public void display();  
} 
public class StatisticsDisplay implements Observer, DisplayElement {  //这是第一个布告板,实时监测气象站记录的数据
    private float maxTemp = 0.0f;  
    private float minTemp = 200;  
    private float tempSum= 0.0f;  
    private int numReadings;//记录观测的次数以便计算平均温度值  
    private Subject weatherData;  //下边几个布告板都会带有主题的对象引用,作用就是能够利用它调用主题的注册、删除观察者的方法,实现监听和放弃监听
  
    public StatisticsDisplay(Subject weatherData) {  
        this.weatherData = weatherData;  
        weatherData.registerObserver(this);  
    }  
    //这属于“推”数据,本类只使用到了第一个参数  
    public void update(float temp, float humidity, float pressure) {  
        tempSum += temp;  
        numReadings++;  
  
        if (temp > maxTemp) {  
            maxTemp = temp;  
        }  
   
        if (temp < minTemp) {  
            minTemp = temp;  
        }  
  
        display();  
    }  
  
    public void display() {  
        System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)  
            + "/" + maxTemp + "/" + minTemp);  
    }  
} 
public class CurrentConditionsDisplay implements Observer, DisplayElement {  
//这是第二个布告板,实时监测气象站记录的数据
  private float temperature;//温度  
  private float humidity;//湿度  
private Subject weatherData; public CurrentConditionsDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } //推数据,这里只使用到了前两个参数 public void update(float temperature, float humidity, float pressure) { this.temperature = temperature; this.humidity = humidity; display(); } public void display() { System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity"); } }
public class ForecastDisplay implements Observer, DisplayElement {  
//这是第三个布告板,实时监测气象站记录的数据
private float currentPressure = 29.92f; private float lastPressure; private Subject weatherData; public ForecastDisplay(Subject weatherData) { this.weatherData = weatherData; weatherData.registerObserver(this); } public void update(float temp, float humidity, float pressure) { lastPressure = currentPressure; currentPressure = pressure; display(); } public void display() { System.out.print("Forecast: "); if (currentPressure > lastPressure) { System.out.println("Improving weather on the way!"); } else if (currentPressure == lastPressure) { System.out.println("More of the same"); } else if (currentPressure < lastPressure) { System.out.println("Watch out for cooler, rainy weather"); } } }

结果展示:

public class WeatherStationHeatIndex {  
  
    public static void main(String[] args) {  
        WeatherData weatherData = new WeatherData();  
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);  
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);  
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);  
        HeatIndexDisplay heatIndexDisplay = new HeatIndexDisplay(weatherData);  
  
        weatherData.setMeasurements(80, 65, 30.4f);  //这里就是模拟的气象站监测数据的变化,人为给了变化的值
        weatherData.setMeasurements(82, 70, 29.2f);  
        weatherData.setMeasurements(78, 90, 29.2f);  
    }  
}  

java提供的Observable类和Observe接口里还有一个标志位,用作判断主体是否改变

https://blog.csdn.net/suool/article/details/39473055具体的可以看这篇文章。


java提供的这两个的缺陷:Observable是一个具体实现类,面向细节了,而未面向抽象,使用Observable时需要使用继承,由于java的类单继承性,如果你的类已经继承了一个类,将不能继承Observable来实现观察者模式,并且由于setChanged和clearChanged方法都是protected的,所以你也不能通过组合来完成观察者模式








猜你喜欢

转载自blog.csdn.net/liuyancainiao/article/details/79960276
今日推荐