Java 设计模式系列(十六)观察者模式(Observer)

Posted binarylei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 设计模式系列(十六)观察者模式(Observer)相关的知识,希望对你有一定的参考价值。

Java 设计模式系列(十五)观察者模式(Observer)

Java 设计模式系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)

  1. Java 设计模式系列(十五)观察者模式(Observer)
  2. Java 设计模式系列(十五)Spring 中的监听器模式

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

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

一、观察者模式的结构

图16-1 观察者模式的结构

  • Subject:目标对象,通常具有如下功能:

    1. 一个目标可以被多个观察者观察

    2. 目标提供对观察者注册和退订的维护

    3. 当目标的状态发生变化时,目标负责通知所有注册的、有效的观察者

  • Observer:定义观察者的接口,提供目标通知时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,以获取目标对象的数据。

  • ConcreteSubject:具体的目标实现对象,用来维护目标状态,当目标对象的状态发生改变时,通知所有注册有效的观察者,让观察者执行相应的处理。

  • ConcreteObserver:观察者的具体实现对象,用来接收目标的通知,并进行相应的后续处理,比如更新自身的状态以保持和目标的相应状态一致。

一个目标可以有任意多个观察者对象,一旦目标的状态发生了改变,所有注册的观察者都会得到通知,然后各个观察者会对通知作出相应的响应,执行相应的业务功能处理,并使自己的状态和目标对象的状态保持一致。

源代码

(1) Subject

/**
 * 目标对象,它知道观察它的观察者,并提供注册和删除观察者的接口
 */
public class Subject {
    /** 用来保存注册的观察者对象 */
    private List<Observer> observers = new ArrayList<Observer>();
    /** 注册观察者对象 */
    public void attach(Observer observer) {
        observers.add(observer);
    }
    /** 删除观察者对象 */
    public void detach(Observer observer) {
        observers.remove(observer);
    }
    /** 通知所有注册的观察者对象 */
    protected void notifyObservers() {
        for(Observer observer : observers){
            observer.update(this);
        }
    }
}

(2) ConcreteSubject

/**
 * 具体的目标对象,负责把有关状态存入到相应的观察者对象,
 * 并在自己状态发生改变时,通知各个观察者
 */
public class ConcreteSubject extends Subject {
    /** 示意,目标对象的状态 */
    private String subjectState;
    public String getSubjectState() {
        return subjectState;
    }
    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
        //状态发生了改变,通知各个观察者
        this.notifyObservers();
    }
}

(3) Observer

/**
 * 观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象
 */
public interface Observer {
    /** 通知观察者 */
    public void update(Subject subject);

}

(4) ConcreteObserver

/**
 * 具体观察者对象,实现更新的方法,使自身的状态和目标的状态保持一致
 */
public class ConcreteObserver implements Observer {
    /** 示意,观者者的状态 */
    private String observerState;
    
    public void update(Subject subject) {
        // 具体的更新实现
        //这里可能需要更新观察者的状态,使其与目标的状态保持一致
        observerState = ((ConcreteSubject)subject).getSubjectState();
    }
}

二、Java 提供的观察者模式

2.1 Java 中的观察者模式

图16-2 Java提供的观察者模式

其中 Observer 和 Observable 是 java.util 下的包。

(1) ConcreteSubject

public class ConcreteSubject extends Observable {
    /** 示意,目标对象的状态 */
    private String subjectState;

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;

        // 状态发生了改变,通知各个观察者
        this.setChanged();
        this.notifyObservers(subjectState);
    }
}

(2) ConcreteObserver

public class ConcreteObserver implements Observer {
    /** 示意,观者者的状态 */
    private String observerState;

    @Override
    public void update(Observable o, Object obj) {
        //这是采用推的方式
        System.out.println("目标推过来的内容是:" + obj);
        //这是获取拉的数据
        System.out.println("主动到目标对象去拉的内容是:" + ((ConcreteSubject)o).getSubjectState());
    }
}

2.2 Java 中的监听者模式

在 java.util 中有两个与事件监有关的类

  • EventObject 事件源,对事件源进行了简单的封装
  • EventListener 事件监听者,标记接口

三、总结

(1) 推模型和拉模型

在观察者模式中,又分为推模型和拉模型两种方式。

  • 推模型:主题对象向观察者推送主题的详细信息,不管观察者是否需要,推送的信息通常是主题对象的全部或部分数据。

  • 拉模型:主题对象在通知观察者的时候,只传递少量信息。如果观察者需要更具体的信息,由观察者主动到主题对象中获取,相当于是观察者从主题对象中拉数据。一般这种模型的实现中,会把主题对象自身通过 update() 方法传递给观察者,这样在观察者需要获取数据的时候,就可以通过这个引用来获取了。


每天用心记录一点点。内容也许不重要,但习惯很重要!

以上是关于Java 设计模式系列(十六)观察者模式(Observer)的主要内容,如果未能解决你的问题,请参考以下文章

设计模式---观察者模式

观察者模式

观察者模式

设计模式(十六)——观察者模式

Saga的实现模式——观察者(Saga implementation patterns – Observer)

(十六)设计模式总结