观察者模式(ObserverPattern)

本文深入解析观察者模式,探讨其核心概念与应用场景。通过具体示例介绍如何利用观察者模式建立对象间一对多的依赖关系,使多个观察者能够自动响应被观察对象的状态变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

观察者模式

定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新;


从上述描述中,我们可知观察者模式主旨是一对多的关系,多个隔离性的对象依赖与一个独特对象,需要获取该对象实时状态;

这个情景如同订阅报纸行为:

  • 报社的业务就是出版报纸;(独特功能对象)
  • 向报社订阅报纸,有新报纸出版,就会向你送来报纸,只要你是他们的订户;
  • 当取消订阅时,它们将停止给你派送报纸;
  • 只要报社运营着,就会有人向他们订阅或者取消订阅;

ObserverPattern
从上述类图中,可以看出观察者模式最关键实现部分是两个接口的使用;


举个栗子:
主题接口,也可称为可观察者接口
Observerable

public interface Observerable {
    //注册观察者资格
    public void registerObserver(Observer observer);
    //取消观察者资格
    public void removeObserver(Observer observer);
    //可观察者状态通知
    public void notifyObserver();
}

观察者接口
Observer

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

可观察者对象实现
WeatherData

public class WeatherData implements Observerable {

    private float temperature;
    private float humidity;
    private float pressure;

    private ArrayList<Observer> observers;//观察者队列

    public WeatherData() {
        observers = new ArrayList<Observer>();
    }

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

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

    @Override
    public void notifyObserver() {
        for (Observer o : observers) {
            o.update(this.temperature, this.humidity, this.pressure);
        }
    }

    public void measurementsChange()
    {
        notifyObserver();
    }

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

观察者对象
CurrentConditionDisplay

public class CurrentConditionDisplay implements Observer, DisplayElement {

    private float temperature;
    private float humidity;

    private Observerable weatherData;

    public CurrentConditionDisplay(Observerable weatherData) {
        this.weatherData = weatherData;
        this.weatherData.registerObserver(this);
    }

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

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

通过上述的解耦,当观察者对象任意增加时我们只需要调用可观察者对象registerObserver()进行注册即可得到可观察者对象的变化,同样也可以依据自身需要进行取消观察;


对于观察者模式的实现,JDK已经提供比较完善的支持:
可观察者对象:
Observable

public class Observable {
    private boolean changed = false;
    private Vector obs;

    public Observable() {
       obs = new Vector();
    }

  public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
  }

  public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }

    public void notifyObservers() {
       notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
       Object[] arrLocal;

       synchronized (this) {        
            if (!changed)
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }

        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    public synchronized void deleteObservers() {
         obs.removeAllElements();
    }

    protected synchronized void setChanged() {
        changed = true;
    }

    protected synchronized void clearChanged() {
        changed = false;
    }

    public synchronized boolean hasChanged() {
        return changed;
    }

    public synchronized int countObservers() {
        return obs.size();
    }
}

观察者对象:

public interface Observer {   
    void update(Observable o, Object arg);
}

通过上面JDK源码查阅,基本所实现的功能都是一模一样的,Observable对象更是提供线程安全的保证,只是采用继承的实现方法给我们自身进行应用带来一点麻烦;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值