观察者模式(订阅模式)

定义

定义对象间一种一对多的关系,使得每当一个对象改变状态,则所有依赖他的对象都会得到通知并被自动更新。

使用场景

1、某些时候需要一些对象有所关联,而且这种关联是可以拆分而不是组合在一起的。

2、某一事件发生,需要向多方触发。

3、消息交换,如消息队列、事件总线的处理机制。

角色

1、Subject:抽象主题,被观察者(Observable)的抽象,管理着众多观察者的实现,可以实现添加或删除观察者的功能。

2、ConcreteSubject:具体主题,被观察者(Observable)的实现,通过该实现来向观察者发送通知。

3、Observer:抽象观察者(Observer),观察者的抽象。一般是接口,实现该接口生成各种各样的观察者。

4、ConcreteObserver:具体观察者,抽象观察者的具体实现,当被观察者发生变化时执行具体逻辑。

简单实现

要实现的功能:定义一个数据订阅源,当数据源发生变化时,订阅者收到消息。


/**
 * 观察者模式(订阅模式)
 */

public class ObservableDesignDemo {
    public static void main(String []args){

        ObserverImp observable1=new ObserverImp("张三");
        ObserverImp observable2=new ObserverImp("李四");




        ObservableImp observableImp=new ObservableImp();
        //将观察者注册到被观察者的观察列表中
        observableImp.addObserver(observable1);
        observableImp.addObserver(observable2);

        //发布消息,notifyObservers()遍历所有的观察者然后调用其update()
        observableImp.observableDoSth("你好,我是被你观察的,我生了变化");

    }
}


/**
 * 被观察者具体实现
 */
class ObservableImp extends Observable{
    void observableDoSth(String sth){
        //表明数据发生了变化且已经通知过
        setChanged();
        notifyObservers(sth);
    }
}


/**
 * 观察者具体实现
 */
class ObserverImp implements Observer {
    String observerName;

    public ObserverImp(String observerName) {
        this.observerName = observerName;
    }

    @Override
    public void update(Observable observable, Object o) {
        System.out.println(observerName+",你订阅的有更新,内容是:"+o);
    }

    @Override
    public String toString() {
        return "观察者的名字是:"+observerName;
    }
}

 

JDK自带类Observable

public class Observable {
    // 1.1 数据是否变化标记
    private boolean changed = false;
    // 1.2 长度自增长数组
    private Vector<Observer> obs;

    /** Construct an Observable with zero Observers. */

    public Observable() {
        obs = new Vector<>();
    }
    // 2.1 添加观察者对象
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }
    // 2.2 删除观察者对象
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
    // 3.1 通知所有观察者
    public void notifyObservers() { 
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
        Object[] arrLocal;
        // 线程同步
        synchronized (this) {
            // 3.2 获取是否发生变化的标记
            if (!hasChanged())
                return;
            // 3.3 转化为 Object 数组
            arrLocal = obs.toArray();
            // 重置标记
            clearChanged();
        }
        // 遍历所有观察者并调用其 update 方法
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }
    // 删除所有观察者对象
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }
    // 设置标记为 true,表明数据发生了变化且已经通知过
    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();
    }
}

 可以看到所有订阅了数据订阅源的人都收到了消息,Observable和Observer是JDK中内置的类,可见观察者模式是非常重要的,这里Observer是抽象的观察者角色,ObserverImp扮演的是具体的观察者角色;Observable扮演的是抽象的主题(被观察者)角色,ObservableImp代表的是具体的主题角色,当ObservableImp有更新时会遍历通知所有的观察者,然后给这些观察者发送一个消息,即ObserverImp的update()方法,这样达到了一对多的通知功能,在这个过程中,通知系统都是依赖Observer和Observable,因此对于ObserverImp和ObservableImp完全没有耦合,保证了订阅系统的灵活性、可扩展性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值