观察者模式(Observer Pattern)


是什么?

怎么用?

什么情况下用?

实例!


 

 

观察者模式:

  一个目标对象管理所有依赖于它的观察者对象,并且当它本身的状态改变时主动发出通知。

  这时候就有问题了,目标怎么知道谁是观察者?谁不是观察者?而且目标要怎么通知观察者?

  (个人感觉两个类通信就能用到这东西)

 

使用场景:

  今日头条文章发布后需要一系列的后续处理流程,比如更新这个作者创建的文章总数、将这篇文章推荐到对应的频道、划分文章的栏目、上报到推荐系统等等。那要其他的这些要怎么知道文章是否发布呢?这时候就可以用到观察者模式了(事件机制)!

 

原理:

  目标类需要:

    1、注册观察者(观察者通知目标:我要当你的观察者)

    2、移除观察者(观察者通知目标:我要溜了)

    3、调用观察者的提供的方法通知观察者

  观察者需要:

    1、提供目标通知观察者时用到的方法

    2、在构造函数中调用目标的注册方法将自己注册成目标的观察者

 

例子:

  气象检测例子:

    如图,气象站是获取实际气象数据的物理设备,WeatherData对象是用来追踪气象站的数据,并更新布告板。

    扩充WeatherData对象,使得布告板能够及时更新,并利于以后的扩展。

    

 

  Subject 是抽象目标,所有的目标都继承这个抽象类,这个抽象类提供了三个最基本的注册、移除、通知观察者的方法!

  WeatherData 是具体目标,继承自抽象目标Subject,这个类的notifyObserver通过调用观察者的udpate方法通知观察者状态变化!

  Observer 是抽象观察者,所有的观察者都继承这个抽象类,这个抽象类提供了udpate方法,以便目标调用。

  CurrentConditionDisplay、StatisticsDisplay 是具体观察者,在这两个类的构造方法中实现了「注册为目标的观察者」!

<Head First 设计模式> code:

package Observer;

public interface Subject {

    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();

}
Subject
package Observer;

import java.util.ArrayList;

public class WeatherData implements Subject{

    private ArrayList observers;
    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 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();
    }
}
WeatherData
package Observer;

public interface Observer {

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

public class CurrentConditionsDisplay implements Observer {

    private float temperature;
    private float humidity;
    private float pressure;
    private Subject weatherDay;

    public CurrentConditionsDisplay(Subject subject) {
        this.weatherDay = subject;
        weatherDay.registerObserver(this);
    }

    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;

        display();
    }

    public void display() {
        System.out.println("temp = " + temperature + " humi = " + humidity + " press = " + pressure);
    }
}
CurrentConditionsDisplay
package com.company;

import Observer.CurrentConditionsDisplay;
import Observer.WeatherData;

public class Main {

    public static void main(String[] args) {

        WeatherData weatherData = new WeatherData();

        CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);

        weatherData.setMeasurements(1, 3, 4);
    }
}
Main

结果:

temp = 1.0 humi = 3.0 press = 4.0

 

posted @ 2019-01-01 01:01  第五  阅读(200)  评论(0编辑  收藏  举报