Java 开发程序员Java 杂谈

Java 理解观察者模式

2019-08-01  本文已影响19人  殷天文

前言:最近在学习RxJava,RxJava在观察者模式的基础上做了扩展,本文带大家了解观察者模式

什么是观察者模式

观察者模式是对象的行为模式,又叫发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。

当对象间存在一对多关系时,适合使用观察者模式。当一个对象被修改时,会自动通知它的依赖对象。观察者模式属于行为型模式。

例如:订单支付成功后,可能会减商品库存,计算会员积分,通知物流发货等等。

观察者模式中的一些概念

将刚刚的例子抽象为观察者模式的话,应该是这样的

image.png

Java API

Java 为我们提供了Observable 和 Observer 两个API,可以用来拓展实现观察者模式

观察者接口很简单,当 被观察者发生改变时,会通过update方法通知所有的 观察者

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

被观察者代码,稍微多了一些,但是也并不复杂。JDK为我们提供了一个线程安全的被观察者模型

public class Observable {
    private boolean changed = false;
    // 观察者集合
    private Vector<Observer> 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();
    }
}

实现

小栗子:公众号发布文章时,推送给所有订阅的用户

/**
 * 公众号
 * (被观察者)
 */
class OfficialAccount extends Observable {
    // 发布文章
    public void publishArticle(String article) {
        setChanged();
        notifyObservers(article);
    }
}
/**
 * 用户
 * (观察者)
 */
class User implements Observer {
    private String username;

    User(String username) {
        this.username = username;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("用户:" + username + ", 收到订阅文章:" + arg);
    }
}
public class Run {
    public static void main(String[] args) {
        OfficialAccount officialAccount = new OfficialAccount();
        User ytw = new User("ytw");
        User hmj = new User("hmj");
        officialAccount.addObserver(ytw);
        officialAccount.addObserver(hmj);
        officialAccount.publishArticle("SpringBoot");
        officialAccount.publishArticle("Java 理解观察者模式");
    }

}

Github传送门

一点理解

在学习观察者模式的时候,总感觉和生产者消费者很像,两者都很好的做到了解耦。上述的观察者模型,如果订阅者很多的话,处理起来效率是很差的(因为是同步的)。个人理解生产者消费者模式属于观察者模式的变种。生产者消费者模式添加了缓冲队列,可以很好的做到异步消息吞吐。

上一篇下一篇

猜你喜欢

热点阅读