观察者模式

来源:互联网 发布:椭圆曲线密码算法属于 编辑:程序博客网 时间:2024/06/06 20:43

    观察者模式是开发中经常用的一个模式。

一、概述

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

        观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

     实现观察者模式,我们应该减少针对实现编程,所以建议使用接口实现。

二、观察者模式的角色组成

 1. 抽象观察者Observer:为所有的具体观察者定义一个接口,所有潜在的观察者必须实现观察者接口,在得到主题通知时更新自己。

 2. 具体观察者ConcreteObserver: 具体观察者可以是任何实现了Observer接口的类。以便使本身的状态与主题的状态协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。

 3. 可观察者(抽象主题)Subject: 主题接口,即可观察者Observable。把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

 4. 具体可观察者(具体主题)ConcreteSubject: 一个具体主题实现了主题接口,将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。

    类图如下:


三、实现观察者模式

 1. 抽象主题角色

主题接口规定了具体主题需要实现的添加,删除及通知观察者更新数据的方法

/** * 抽象主题,被观察者 * */public interface Subject {    /**     * 添加观察者     *      * @param observer     */    void addObserver(Observer observer);    /**     * 移除指定的观察者     *      * @param observer     */    void removeObserver(Observer observer);    /**     * 移除所有的观察者     */    void removeAll();    /**     * data 是要通知给观察者的数据 因为Object是所有类的父类,可以使用多态,当然 你也可以使用 泛型     *      * @param data     */    void notifyAllObserver(Object data);    /**     * 单独 通知某一个观察者     *      * @param observer     * @param data     *            data 是要通知给观察者的数据 因为Object是所有类的父类,可以使用多态,当然 你也可以使用 泛型     */    void notify(Observer observer, Object data);}
2. 抽象观察者角色

观察者接口规定了具体观察者用来更新数据的方法

/** * 抽象观察者接口 */public interface Observer {    /**     *      * @param subject 被观察者     * @param data    被观察者传递给观察者的 数据     */    void update(Subject subject,Object data);}

3. 具体主题角色(被观察者)

public class ConcreteSubject implements Subject{ //观察者集合,用于管理所有的观察者    List<Observer> mList = new ArrayList<>();    @Override    public void addObserver(Observer observer) {        // TODO Auto-generated method stub        // 确保相同的观察者只含有一个        if (observer == null) {            throw new NullPointerException("observer == null");        }        if (!mList.contains(observer)) {            mList.add(observer);        }    }    @Override    public void removeObserver(Observer observer) {        // TODO Auto-generated method stub        mList.remove(observer);    }    @Override    public void removeAll() {        // TODO Auto-generated method stub        mList.clear();    }    @Override    public void notifyAllObserver(Object data) {        // TODO Auto-generated method stub        for (Observer observer : mList) {            observer.update(this, data);        }    }    @Override    public void notify(Observer observer, Object data) {        // TODO Auto-generated method stub        if (observer != null) {            observer.update(this, data);        }    }}

4. 具体的观察者角色

  可以定义多个具体观察者

  观察者One

public class ObserverOne implements Observer {    @Override    public void update(Subject subject, Object data) {        // TODO Auto-generated method stub        System.err                .println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString());    }}
观察者Two

public class ObserverTwo implements Observer {    @Override    public void update(Subject subject, Object data) {        // TODO Auto-generated method stub        System.err        .println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString());    }}

观察者Three

public class ObserverThree implements Observer {    @Override    public void update(Subject subject, Object data) {        // TODO Auto-generated method stub        System.err        .println("the messge from subject to-->" + this.getClass().getName() + "<---is " + data.toString());    }}

下面是具体的测试类

public class TestObservePattern {public static void main(String[] args) {        // TODO Auto-generated method stub        ConcreteSubject concreteSubject = new ConcreteSubject();        ObserverOne observerOne=new ObserverOne();        ObserverTwo observerTwo=new ObserverTwo();        ObserverThree observerThree=new ObserverThree();        concreteSubject.addObserver(observerOne);        concreteSubject.addObserver(observerTwo);        concreteSubject.addObserver(observerThree);        //通知所有的观察者        concreteSubject.notifyAllObserver("wake up,wake up");        //通知某个特定的观察者OberverTwo        concreteSubject.notify(observerTwo, "Specila msg  for you");        //观察者ObserveThree 决定不再订阅主题        concreteSubject.removeObserver(observerThree);        //通知所有的观察者        concreteSubject.notifyAllObserver("new Message come ");    }}
运行截图



通过日志可以看到:
主题内容更新后,所有的观察者将接收到更新结果。
某个特定的观察者取消对主题的订阅后,自身不再接收到主题的更新,而且也不影响主题的实现

四、小结

  观察者模式使用场景

      1. 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
      2. 事件多级触发场景。
      3. 跨系统的消息交换场景,如消息队列、事件总线的处理机制。



PS: 文中的实例代码 摘录自观察者模式。

0 0
原创粉丝点击