Chapter 2 The Observer Pattern

概述

它可以让你时刻对对象了如指掌。
对象可以在运行时决定无论是否有消息通知它们。
观察者模式的两个组成部分是发布者和订阅者。
在观察者模式中发布者被称为目标(subject)订阅者被称为观察者(observer)。
目标和观察者之间建立了某种联系,目标中包含着各种数据,观察者获取这些数据,只要目标中有数据变动就通知观察者。一个不相关的对象要想成为该目标的观察者就必须要注册成为该目标的观察者,一个观察者也只有通过注销才能成为一个不相关的对象。这就是观察者模式的主要思想。
观察者模式的正式定义:它是一种1对多的依赖关系,即,一个目标多个观察者,每当观察者有变化时所有观察者都会得到消息并可能发生相应的变化。在观察者模式中观察者和目标以及观察者之间都是彼此独立的。
P64给出了观察者模式中的类图设计。
在该图中Subject是一个接口,它规定了注册、注销、通知观察者等几个方法。
Observer也是个接口,它规定了更新的行为。
Subject和Observer之间是1对多的关系。
要注册成为Subject的对象就必须去实现Subject接口中的方法,此外,它还可以有设置自身状态的存取器。
要成为Observer的对象就必须去实现Observer接口中的方法。
图中的实箭头代表关联关系,虚箭头代表实现。
观察者模式提供了松散耦合,松散耦合可以使对象之间在互不知晓的情况下彼此互动。
在彼此互动的对象之间力求做到松散耦合
因为它最小化了对象之间的依赖关系,不会引起牵一发而动全身的情况。
P65列举了它的好处。
JAVA本身有内置的观察者模式API。
JAVA中的interface代表了一种抽象的功能,它不一定被实现但是它是某一类实现的通用载体,因此你想使用一类功能只需要引入一个interface的对象即可。它是具体实现细节的上一层次,是对软件模块之间联系的把握。

代码层面

被观察者的setter是触发观察者刷新的关键所在,所以直接点说观察者是基于setter实现的。被观察者还必须维护一个观察者的对象容器,订阅和注销就是对容器的操作而已。

类图

观察者模式

依赖关系是个啥关系?

说得太官方了很抽象难懂,所以整点俗话。依赖关系就是A中有一部分用到了B,这就叫A依赖B。拿本例来说Subject中的方法参数是Observer类型的,于是说Subject是依赖Observer的。你中有我,但我中没有你,则你依赖我。依赖方依赖被依赖方,依赖方在箭尾,被依赖方在箭头。需要注意的是B并不属于A,而所谓属于是指B是A的成员。比方说你要做饭发现刀坏了,于是向别人借刀,于是你就依赖别人了,因为那刀不是你的。

使用

package com.company;

public class Main {

    public static void main(String[] args) {
    // write your code here
        SubjectEntity subjectEntity = new SubjectEntity();
        ObserverEntity observer1 = new ObserverEntity();
        ObserverEntity observer2 = new ObserverEntity();

        subjectEntity.addObserver(observer1);
        subjectEntity.addObserver(observer2);

        subjectEntity.setValue(1);
        subjectEntity.setValue(9);

        subjectEntity.removeObserver(observer2);

        subjectEntity.setValue(2);
    }
}

输出

被观察者设置值1
观察者内部:1
观察者内部:1
被观察者设置值9
观察者内部:9
观察者内部:9
被观察者设置值2
观察者内部:2

Process finished with exit code 0

实现

Interface Subject

package com.company;

public interface Subject {
    /**
     * 因为观察者实现Observer接口所以它也是个
     * Observer对象了。
     * @param observer
     */
    void addObserver(Observer observer);//注册成为观察者
    void removeObserver(Observer observer);//注销。
    void notifyObserver(int value);//通知观察者
}

被观察者实体SubjectEntity

package com.company;

import java.util.ArrayList;
import java.util.List;

public class SubjectEntity implements Subject {
    private int value;
    private List<Observer> observerList;//这个是必须的,用来存储观察者的。

    public SubjectEntity() {
        this.observerList = new ArrayList<>();
    }

    /**
     * 这个也是必需的,因为它是触发观察者更新的
     * 根本原因。
     * @param value
     */
    public void setValue(int value) {
        System.out.println("被观察者设置值" + value);
        this.value = value;;
        this.notifyObserver(this.value);
    }

    @Override
    public void addObserver(Observer observer) {
        if (!this.observerList.contains(observer))
            observerList.add(observer);
    }

    @Override
    public void removeObserver(Observer observer) {
        if (this.observerList.contains(observer))
            observerList.remove(observer);
    }

    @Override
    public void notifyObserver(int value) {
        for (Observer element:this.observerList)
            element.updateObserver(value);
    }
}

interface Observer观察者

package com.company;

public interface Observer {
    void updateObserver(int value);//更新观察者。
}

观察者实体ObserverEntity

package com.company;

public class ObserverEntity implements Observer {
    public ObserverEntity() {
    }

    @Override
    public void updateObserver(int value) {
        System.out.println("观察者内部:" + value);
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 场景问题# 1.1 订阅报纸的过程## 来考虑实际生活中订阅报纸的过程,这里简单总结了一下,订阅报纸的基本流程...
    七寸知架构阅读 4,694评论 5 57
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,993评论 1 15
  • 面向对象的六大原则 单一职责原则 所谓职责是指类变化的原因。如果一个类有多于一个的动机被改变,那么这个类就具有多于...
    JxMY阅读 976评论 1 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,079评论 19 139
  • 前言 在使用vapor做的后端应用已经在heroku上跑了有一段时间,也遇到一些问题,下面这个问题就是博主在升级了...
    AgoniNemo阅读 1,240评论 0 0