首页 > 技术文章 > 设计模式之观察者模式

zjiuwei 2018-09-10 21:39 原文

观察者模式:定义对象间的一种一对多的依赖关系,当一个对象状态发生改变时,所有依赖它的对象都得道通知并被自动更新。
别名:依赖、发布-订阅

这一模式的关键对象是目标和观察者,一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的观察者都得道通知。作为对通知的响应,
每个观察者都将查询目标以使其状态与目标状态同步。

什么情况下使用观察者模式?
1、当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中以使他们各自独立地改变和复用。
2、当一个对象的改变同时改变其他对象,而不知道具体有多少对象有待改变。
3、当一个对象必须通知其他对象,而它又不能假定其他对象是谁。

目标通知观察者的方式:
1、广播的方式:将通知广播给所有它的观察者,而不关系对方是否需要,观察者决定处理还是忽略这个通知。

观察者对消息的处理:
* 推模型:目标向观察者发送改变的所有信息,这些信息可能不是观察者对象全部都需要的,观察者根据收到的信息更新自己的数据。
* 拉模型:目标仅向观察者发送很少的信息,当观察者收到目标发送的信息后,还需要主动向目标获取它需要的信息。

更改管理器:
* 1、它维护目标到它的观察者之间的映射关系,这就不需要目标来维护队其观察者的引用。
* 2、它定义了一个特定的更新策略。
* 3、根据一个目标的请求,它更新所有依赖这个目标的观察者。
更改管理器通知观察者需要做异步处理,否则某个观察者存在阻塞操作,会导致通知其他观察者更新的操作被阻塞。

package observer;

/**
 * 观察者接口,一个观察者可以观察(订阅)多个目标。
 * 观察者更新数据可以有两种方式:推模型和拉模型。
 * 推模型:目标向观察者发送改变的所有信息,这些信息可能不是观察者对象全部都需要的,观察者根据收到的信息更新自己的数据。
 * 拉模型:目标仅向观察者发送很少的信息,当观察者收到目标发送的信息后,还需要主动向目标获取它需要的信息。
 */
public interface Observer {
    void update();
}
package observer;

public interface Subject {
    void attach(Observer observer);
    void detach(Observer observer);
    void notifyObserver();
}
package observer;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 这是一个更改管理器,它的作用有三点:
 * 1、它维护目标到它的观察者之间的映射关系,这就不需要目标来维护队其观察者的引用。
 * 2、它定义了一个特定的更新策略。
 * 3、根据一个目标的请求,它更新所有依赖这个目标的观察者。
 * <p>
 * 更改管理器更新(注册和解除注册)动作可能会被多个目标同时出发,所以这两个操作应该是线程安全的。
 */
public abstract class ChangeManager {
    //维护目标对象和它的观察者之间的映射关系,volatile保证多线程情况下映射关系的可见性。
    protected volatile Map<Subject, Set<Observer>> map = new ConcurrentHashMap<>();

    /**
     * 注册观察者和目标对象的映射关系
     *
     * @param subject
     * @param observer
     */
    synchronized void register(Subject subject, Observer observer) {
        /**
         * 更改管理器更新(注册和解除注册)动作可能会被多个目标同时出发,所以这两个操作应该是线程安全的。
         * 虽然使用了ConcurrentHashMap,但更新目标对象的观察者列表不是线程安全的,所以这里对目标对象加锁。
         * ConcurrentHashMap保证不同主题间的更改是线程安全的。
         */
        Set<Observer> subList = map.get(subject);
        if (subList == null || subList.size() == 0) {
            map.put(subject, Set.of(observer));
        } else {
            subList.add(observer);
            map.put(subject, subList);
        }
    }

    /**
     * 解除目标对象与它的观察者关系映射
     *
     * @param subject
     * @param observer
     */
    synchronized void unRegister(Subject subject, Observer observer) {
        Set<Observer> subList = map.get(subject);
        if (subList != null || subList.size() > 0) {
            subList.remove(observer);
            map.put(subject, subList);
        }
    }

    /**
     * 通知观察者
     */
    abstract void notifyObserver(Subject subject);

}

 

推荐阅读