java设计模式——观察者模式(Observer Pattern)

2023-11-01

概述:
       观察者模式是使用频率最高的设计模式之一,它用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展。
定义:
       定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
结构:
  • Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify()。目标类可以是接口,也可以是抽象类或具体类。
  • ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
  • Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。
  • ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者Observer中定义的update()方法。通常在实现时,可以调用具体目标类的addObserver()方法将自己添加到目标类的集合中或通过deleteObserver()方法将自己从目标类的集合中删除。
UML图:
场景:在平时生活中有很多场景都有观察者模式的影子,比如商城宣传、街头艺人、马路交通信号灯等等,这里就举一个过马路的例子,一般十字路口都会有红绿灯,不管行人还是车辆都要根据交通信号灯的信号来确定什么时候过马路,红灯停、绿灯行,这是小学都学过的交通规则了,当然不守交通规则的sb不算。这里的交通信号灯就相当于目标(被观察者),行人或者司机属于观察者。
代码分析:
/**
 * Created by **
 *  目标抽象类
  */
public abstract class Subject {
    private ArrayList<Observer>  observers new ArrayList<Observer>();

    /**
     *  增加观察者
      @param  observer
      */
    public void addObserver(Observer observer){
        observers.add(observer);
    }

    /**
     *  移除观察者
      @param  observer
      */
    public void deleteObserver(Observer observer){
        observers.remove(observer);
    }

    /**
     *  向观察者发出通知
      @param  string
      */
    public void notifyObservers(String string){
        for (Observer observer :  observers) {
            observer.update(string);
        }
    }
}
/**
 * Created by **
 *  交通信号灯:具体目标
  */
public class TrafficLight  extends Subject {
    /**
     *  显示红灯
      */
    public void showRedLight(){
        LogFactory. log( " 红灯亮了 ");
        super.notifyObservers( "red");
    }
    /**
     *  显示绿灯
      */
    public void showGreenLight(){
        LogFactory. log( " 绿灯亮了 ");
        super.notifyObservers( "green");
    }
}
/**
 * Created by **
 *  观察者接口
  */
public interface Observer {
    //  更新操作
    public void update(String string);
}
/**
 * Created by **
 *  司机:观察者
  */
public class Driver  implements Observer {
    @Override
    public void update(String string) {
        LogFactory. log( "E lights :"+string);
        if ( "red".equals(string)){
            stop();
        } else if ( "green".equals(string)){
            travel();
        } else {
            LogFactory. log( " 交通信号灯坏了? ...");
        }
    }

    private void travel(){
        LogFactory. log( " 绿灯亮了,可以过马路了 ");
    }

    private void stop(){
        LogFactory. log( " 红灯亮了,停止前行 ");
    }
}
客户端调用:
TrafficLight trafficLight =  new TrafficLight();

Driver driver =  new Driver();

trafficLight.addObserver(driver);

trafficLight.showGreenLight();

try {
    Thread. sleep( 2000);
    trafficLight.showRedLight();
catch (InterruptedException e) {
    e.printStackTrace();
}
log输出:
08-19 15:14:41.842 2648-2648/? D/test: 绿灯亮了
08-19 15:14:41.842 2648-2648/? D/test: E lights :green
08-19 15:14:41.842 2648-2648/? D/test: 绿灯亮了,可以过马路了
08-19 15:14:43.842 2648-2648/? D/test: 红灯亮了
08-19 15:14:43.842 2648-2648/? D/test: E lights :red
08-19 15:14:43.842 2648-2648/? D/test: 红灯亮了,停止前行
      上述例子,我只是添加了一个观察者,如果要添加多个观察者直接调用addObserver方法即可,另外观察者模式在java语言中的地位非常重要所以jdk里边提供了相关的接口来支持该模式。
JDK提供的Observable类及Observer接口:
  • Observer接口:相当于观察者接口。该接口只声明一个方法:update(Observable observable, Object data)。
  • Observable类:相当于目标抽象类(Subject)。该抽象类中有多个方法:
          
下面将上述代码做一下修改,将具体的目标类继承Observable,将具体的观察者类实现Observer接口:
/**
 * Created by **
 *  交通信号灯:具体目标
  */
public class TrafficLight  extends Observable {
    /**
     *  显示红灯
      */
    public void showRedLight(){
        LogFactory. log( " 红灯亮了 ");
        super.setChanged();
        super.notifyObservers( "red");
    }
    /**
     *  显示绿灯
      */
    public void showGreenLight(){
        LogFactory. log( " 绿灯亮了 ");
        super.setChanged();
        super.notifyObservers( "green");
    }
}
/**
 * Created by **
 *  司机:观察者
  */
public class Driver  implements Observer {
    /*@Override
    public void update(String string) {
        LogFactory.log("E lights :"+string);
        if ("red".equals(string)){
            stop();
        }else if ("green".equals(string)){
            travel();
        }else {
            LogFactory.log(" 交通信号灯坏了? ...");
        }
    }*/
    @Override
    public void update(Observable observable, Object data) {
        LogFactory. log( "E lights :"+data);
        if ( "red".equals(data.toString())){
            stop();
        } else if ( "green".equals(data.toString())){
            travel();
        } else {
            LogFactory. log( " 交通信号灯坏了? ...");
        }
    }
    private void travel(){
        LogFactory. log( " 绿灯亮了,可以过马路了 ");
    }

    private void stop(){
        LogFactory. log( " 红灯亮了,停止前行 ");
    }

}
客户端的代码不需要更改,最后log输出都是一样一样的,你们可以自己验证一下。
优点:
  • 观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
  • 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
  • 观察者模式支持广播通信。
  • 观察者模式符合“开闭原则”的要求。
缺点:
  • 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
适用环境:
  • 一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
  • 一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
  • 一个对象必须通知其他对象,而并不知道这些对象是谁。
  • 需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
扩展:
      MVC模式是一种架构模式,它包含三个角色:模型(Model),视图(View)和控制器(Controller)。观察者模式可以用来实现MVC模式,观察者模式中的观察目标就是MVC模式中的模型(Model),而观察者就是MVC中的视图(View),控制器(Controller)充当两者之间的中介者(Mediator)。当模型层的数据发生改变时,视图层将自动改变其显示内容。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java设计模式——观察者模式(Observer Pattern) 的相关文章

  • 设计模式的 C++ 实现---原型模式

    前文回顾 单例模式 一 单例模式 二 观察者模式 简单工厂模式 工厂方法模式 一 工厂方法模式 二 抽象工厂模式 一 抽象工厂模式 二 前言 原型模式指直接用一个已经存在的对象来创建一个新的对象 然后对新对象进行稍微修改即可 类似复制的操作
  • 23种设计模式之装饰模式

    装饰模式 一个简陋的房子 它可以让人在里面居住 为人遮风避雨 但如果给它进行装修 那么它的居住环境就更加宜人了 程序中的对象也与房子十分类似 首先有一个相当于 房子 的对象 然后经过不断装饰 不断对其增加功能 它就变成了使用功能更加强大的对
  • 设计模式-单一职责原则介绍与理解

    描述 一个类应该专注于实现一个功能 好处 便于代码复用 举例 俄罗斯方块游戏 首先可以想到的是游戏逻辑与界面的分离 也就是说逻辑一个类 界面部分一个类 这样做的好处就是我们可以复用游戏逻辑的代码 例如我们用java写了一个基于PC端的俄罗斯
  • python语法(高阶)-设计模式(单例模式)

    参考内容 黑马程序员
  • C++ 装饰器模式

    什么是装饰器模式 装饰器模式是一种结构型设计模式 实现了在不改变现有对象结构的的同时又拓展了新的功能 装饰器本质上是对现有对象的重新包装 同时装饰器又称为封装器 如何理解装饰器模式 以笔记本电脑为例 当我们购买了一台新笔记本电脑 但我们发现
  • C++设计模式(二)观察者模式

    1 观察者模式知识点 1 定义 定义对象间的一种一对多的依赖关系 当一个对象的状态发生改变的时候 所有依赖它的对象都得到通知并自动更新 2 动机 将一个系统分割成一系列相互协作的类有一个常见的副作用 需要维护相关对象间的一致性 我们不希望为
  • 简单工厂模式

    简单工厂模式 一 概念 从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫做静态工厂方法 StaticFactory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简
  • C++设计模式-State状态模式

    State状态模式作用 当一个对象的内在状态改变时允许改变其行为 这个对象看起来像是改变了其类 UML图如下 State类 抽象状态类 定义一个接口以封装与Context的一个特定状态相关的行为 ConcreteState类 具体状态 每一
  • 六大设计原则--开闭原则

    定义 software entities like classes modules and functions should be open for extension but closed for modifications 一个软件实体
  • 设计模式——简单工厂模式

    简单工厂模式定义为 简单工厂模式又称为静态工厂方法模型 它属于类创建型模式 在简单工厂模式中 可以根据参数的不同返回不同类的实例 简单工厂专门定义一个类来负责创建其他类的实例 被创建的实例通常都具有共同的父类 简单工厂模式结构图 简单工厂模
  • 设计模式——导论

    作为软件开发人员 我们在平时工作的过程中 往往需要编写很多的代码来实现我们的需求 很多的时候会造成代码臃肿和代码冗余的情况 这个时候我们需要引入一个理念 设计模式 设计模式存在的意义在于 1 使得我们的代码更加精炼 2 使我们代码的可读性更
  • 设计模式学习之装饰器模式

    装饰器 Decorator 模式跟适配器 Adapter 模式一样 属于构建型设计模式 在学习适配器模式的时候说过 适配器模式的重点在复用能力 装饰器模式的重点在扩展能力 换言之 装饰器模式是先复用后扩展 这也导致了很多人跟适配器模式混淆
  • [设计模式]模板方法模式(Template Method)

    1 意图 定义一个操作中的算法的骨架 而将一些步骤延迟到子类中 TemplateMethod使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤 2 动机 其实就是如意图所描述的 算法的骨架是一样的 就是有些特殊步骤不一样 就可以
  • Java设计模式之装饰者设计模式Decorator Pattern

    目录 一 基本概念 二 结构 1 图示 三 案例演示 被装饰对象的基类 一个接口 有cost 和description 两个抽象方法 具体被装饰的对象 实现上面这个接口 装饰者抽象类 基类 实现drink接口 具体的装饰者类 糖 具体装饰者
  • 程序员必知的23种设计模式之组合模式

    文章目录 1 模式引出 学校院系展示需求 1 1 传统方案 1 2 传统方案问题分析 2 组合模式基本介绍 2 1 方案修改 3 组合模式解决的问题 4 组合模式的注意事项和细节 1 模式引出 学校院系展示需求 编写程序展示一个学校院系结构
  • 设计模式(不懂)

    面试中经常问到设计模式 我才对这个东西了解了一下 才发现他是没有开发的新大陆 是oo设计的更高级别 能把设计模式搞懂 那oo你就搞的差不多了 随便看了还是很有意思的 虽然不怎么懂 百科名片 相关书籍 设计模式 Design pattern
  • 设计模式(3)--对象结构(5)--外观

    1 意图 为子系统中的一组接口提供一个一致的界面 Facade模式定义了一个高层接口 这个接口使得 这一子系统更加容易使用 2 两种角色 子系统 Subsystem 外观 Facade 3 优点 3 1 对客户屏蔽了子系统组件 减少了客户处
  • 设计模式 原型模式 与 Spring 原型模式源码解析(包含Bean的创建过程)

    原创 疯狂的狮子Li 狮子领域 程序圈 2023 12 19 10 30 发表于辽宁 原型模式 原型模式 Prototype模式 是指 用原型实例指定创建对象的种类 并且通过拷贝这些原型 创建新的对象 原型模式是一种创建型设计模式 允许一个
  • 自动化测试面试题(附答案)

    1 自动化代码中 用到了哪些设计模式 单例设计模式 工厂模式 PO设计模式 数据驱动模式 面向接口编程设计模式 2 什么是断言 Assert 断言Assert用于在代码中验证实际结果是不是符合预期结果 如果测试用例执行失败会抛出异常并提供断
  • C++设计模式 #3策略模式(Strategy Method)

    动机 在软件构建过程中 某些对象使用的的算法可能多种多样 经常改变 如果将这些算法都写在类中 会使得类变得异常复杂 而且有时候支持不频繁使用的算法也是性能负担 如何在运行时根据需求透明地更改对象的算法 将算法和对象本身解耦 从而避免上述问题

随机推荐

  • 仓位管理 – 2.实战篇

    上一篇 说到了仓位管理的重要性 这一篇则说明我对仓位控制算法的设计 以及最终使用的算法 由于内容较多 本文中我尽量只说重点 概念 算法 就是将一定可变范围内的一组输入条件 轮换到确定的输出时 所使用到的逻辑换算关系 仓位控制算法 其输入就是
  • study

    学习的博客地址 1 对自己python有帮助过的博客 http blog csdn net anbo724 article category 831447 另外有hadoop 等其他分类
  • 机器学习--人脸自动补齐(11)

    随机树ExtraTreeRegressor 分列点随机选取 不考虑信息增益 减少过拟合 获取一个对象所属的类名称 model class name import numpy as np import pandas as pd import
  • 肖臻老师区块链公开课笔记

    前段时间 区块链大火 出现了很多种基于区块链技术的政务应用 之前通过零散的网页信息和讲座 自我感觉理解了block chain原理 当看到各种区块链技术广泛应用时 自己以技术理解 反而对之不屑 当然 也怀疑自己还没有理解了区块链 带着这种好
  • 二、Flink使用异步算子请求高德地图获取位置信息

    目录 Flink异步算子使用介绍 Flink使用异步算子请求高德地图获取位置信息代码实现 相关阅读 Flink使用异步算子 线程池查询MySQL 1 概述 1 Flink异步算子使用介绍 1 异步与同步概述 同步 向数据库发送一个请求然后一
  • 一步步学习SPD2010--第二章节--处理SP网站(6)---- 探索SP网站

    SP技术没有一个界面 你可以通过使用Web浏览器或者兼容程序如Office 应用程序 包括SPD 你可以选择适合你必须完成的任务的接口 然而 根据你选择的程序 你可能有SP网站的不同视图 如果你使用MS Word 你只看到了网站和内容的一小
  • 爆肝整理 JVM 十大模块知识点总结,不信你还不懂

    01 JVM 内存结构 Java 虚拟机的内存空间分为 5 个部分 程序计数器 Java 虚拟机栈 本地方法栈 堆 方法区 JDK 1 8 同 JDK 1 7 比 最大的差别就是 元数据区取代了永久代 元空间的本质和永久 代类似 都是对 J
  • 【ESP32开发】——RGB LED灯(灯珠)点亮

    一 引言 本章内容主要介绍如何使用ESP32开发板点亮板载的RGB灯 使用的是ESP32 S3和ESP32 C3开发板 调用第三方库实现 由于网络上没有关于点亮ESP32板载RGB灯的资料 特此记录 二 ESP32 C3与ESP32 S3
  • python怎么批量处理数据_python操作数据之批量添加数据

    import pymysql import random import time from datetime import datetime type dict 测试01 001 测试02 002 测试03 003 测试04 004 fid
  • bind详解

    bind与占位符 绑定普通函数 绑定成员函数 绑定函数对象 如果你还在使用bind1st bind2nd 那么恐怕已经out了 Boost提供了更强大的武器bind 用于函数对象的绑定 bind接受的第一个参数必须是可调用对象f 包括函数
  • CentOS7.2安装Weblogic12c出现的问题

    Weblogic12c安装到步骤 Prerequisite Checks 时 会进行操作系统版本的校验 即checking operating system certification 此处操作系统版本会校验不过去 如下图 解决方案 修改
  • 刷脸生物支付有唯一性和不可替代性

    刷脸支付的时代 特别是刷脸支付解决了扫码支付需要手机为载体的痛点 在移动支付中生物支付以其唯一性和不可替代性 正在逐步替代传统的金融支付工具 引领未来支付结算模式 移动支付衍生的刷脸支付其核心技术就是人工智能中人脸识别技术 刷脸支付自然也是
  • 0027算法笔记——【回溯法】回溯法与装载问题

    1 回溯法 1 描述 回溯法是一种选优搜索法 按选优条件向前搜索 以达到目标 但当探索到某一步时 发现原先选择并不优或达不到目标 就退回一步重新选择 这种走不通就退回再走的技术为回溯法 2 原理 回溯法在问题的解空间树中 按深度优先策略 从
  • 自定义时间Toast(只弹一次)

    CToast类 package com pinkman dota util import com pinkman dota R import android content Context import android graphics C
  • Linux 系统的运行级别(Run Level)

    Linux 操作系统自从开始启动至启动完毕需要经历几个不同的阶段 这几个阶段就叫做 Runlevel 同样 当Linux操作系统关闭时也要经历另外几个不同的 Runlevel 下面详细介绍一下 Runlevel 并展示一些小技巧来让Linu
  • 2021最新Java常用开源库总结,思维导图+源代码+笔记+项目

    蚂蚁金服 五面 蚂蚁金服 一面 一面就做了一道算法题 要求两小时内完成 给了长度为N的有重复元素的数组 要求输出第10大的数 典型的TopK问题 快排算法搞定 算法题要注意的是合法性校验 边界条件以及异常的处理 另外 如果要写测试用例 一定
  • 2020-10-24 无内容,请勿点击

    1024
  • idea启动Tomcat报错:Application Server was not connected before run configuration stop..

    使用IDEA开启Tomcat时候报了这么个错 Application Server was not connected before run configuration stop reason Unable to ping server a
  • Java3D的场景图结构

    Java3D的场景图结构 Java3D实际上是Java语言在三维图形领域的扩展 与Java一样 Java3D有纯粹的面向对象结构 Java3D的数据结构采用的是Scene Graphs Structure 场景图 就是一些具有方向性的不对称
  • java设计模式——观察者模式(Observer Pattern)

    概述 观察者模式是使用频率最高的设计模式之一 它用于建立一种对象与对象之间的依赖关系 一个对象发生改变时将自动通知其他对象 其他对象将相应作出反应 在观察者模式中 发生改变的对象称为观察目标 而被通知的对象称为观察者 一个观察目标可以对应多