观察者模式

本文详细介绍了观察者模式的基本概念和应用场景,通过实例演示了如何在Java中实现观察者模式,包括自定义实现和利用Java内置的Observable类。

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

一、基本概念

1、定义:
定义对象间的一种一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都能得到通知并被自动更新。 例如:天气预报服务,一旦你订阅该服务,,每天一旦有天气信息更新,它就会及时向你发送最新的天气信息。
2、结构图

  • Subject:抽象被观察者,会将所有观察者对象保存到一个集合中,提供方法来添加和删除观察者。
  • ConcreteSubject:具体被观察者,如自身发生改变,给所有注册的观察者发通知。
  • Observer:抽象观察者,定义更新接口,如果接受到被观察者的通知后,自身进行更新。
  • ConcreteObserver:具体观察者,实现更新接口

二、相关实例

定义天气作为被观察者,如果天气更新,观察者进行数据更新
1、Subject

/**
 * 被观察者接口
 */
public interface Subject {
    //注册观察者
    void registObserver(Observer observer);
    //取消注册
    void unRegistObserver(Observer observer);
    //通知观察者
    void notifiObservers();
}
复制代码

2、Observer

/**
 * 观察者接口
 */
public interface Observer<T> {
    //数据更新
    void update(T t);
}
复制代码

3、ConcreteSubject

public class Weather implements Subject {
    private Vector<Observer> mObservers = new Vector<>();
    public int mTemp;
    @Override
    public void registObserver(Observer observer) {
        this.mObservers.add(observer);
    }

    @Override
    public void unRegistObserver(Observer observer) {
        this.mObservers.remove(observer);
    }

    @Override
    public void notifiObservers() {
        for (Observer observer : mObservers) {
            observer.update(this);
        }
    }

    /**
     * 温度更新后,通知被观察者
     * @param temp
     */
    public void updateTemp(int temp){
	    this.mTemp = temp;
        notifiObservers();
    }
}
复制代码

4、ConcreteObserver

public class Forecast implements Observer<Weather>{
    @Override
    public void update(Weather weather) {
        System.out.println("温度调整为:"+weather.mTemp);
    }
}
复制代码

5、使用:

public class ObserverTest {
    public static void main(String[] args){
        Weather weather = new Weather();
        Forecast forecast = new Forecast();
        //注册观察者
        weather.registObserver(forecast);
        //被观察者数据有更新
        weather.updateTemp(15);
    }
}
复制代码

结果:

当天气有温度更新时,天气预报会收到相应的通知,并进行对应的更新。

三、java.util.Observable源码解析

java中提供了Observerable和Observer相关实现类
1、java.util.Observable

public class Observable {
    private boolean changed = false;
    private final ArrayList<Observer> observers;

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

    //添加观察者
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!observers.contains(o)) {
            observers.add(o);
        }
    }

    //删除观察者
    public synchronized void deleteObserver(Observer o) {
        observers.remove(o);
    }

    //通知观察者
    public void notifyObservers() {
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {

        Observer[] arrLocal;

        synchronized (this) {
            //当changed为true的时候才通知观察者
            if (!hasChanged())
                return;

            arrLocal = observers.toArray(new Observer[observers.size()]);
            clearChanged();
        }

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

    public synchronized void deleteObservers() {
        observers.clear();
    }

    //将changed设为true
    protected synchronized void setChanged() {
        changed = true;
    }

    //清除状态
    protected synchronized void clearChanged() {
        changed = false;
    }

    //查询状态
    public synchronized boolean hasChanged() {
        return changed;
    }


    public synchronized int countObservers() {
        return observers.size();
    }
}
复制代码

2、java.util.Observer

public interface Observer {

    void update(Observable o, Object arg);
}
复制代码

3、实例调用:
(1)被观察者

public class Weather extends Observable {
    public int mTemp;

    /**
     * 温度更新后,通知被观察者
     * @param temp
     */
    public void updateTemp(int temp){
        this.mTemp = temp;
        setChanged();
        notifyObservers(this);
    }
}
复制代码

(2)观察者

public class Forecast implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof Weather) {
            System.out.println("温度调整为:"+((Weather) arg).mTemp);
        }
    }
}
复制代码

(3)使用

public class ObserverTest {
    public static void main(String[] args) {
        Weather weather = new Weather();
        Forecast forecast = new Forecast();
        weather.addObserver(forecast);
        weather.updateTemp(20);
    }
}
复制代码

结果:观察者接受到了通知并进行了更新

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值