Java设计模式之一:观察者模式

news2024/9/21 16:42:45

目录

一、什么是观察者模式

二、如何使用观察者模式

三、观察者模式的优势和使用场景


 

一、什么是观察者模式

观察者模式是一种常见的设计模式,用于在对象之间建立一对多的依赖关系。在该模式中,一个主题(被观察者)维护了一个观察者列表,并在自身状态发生变化时通知所有观察者进行相应的更新。

观察者模式的核心概念包括以下几个角色:

  1. 主题(Subject):也称为被观察者或发布者,它维护了一个观察者列表,并提供方法用于注册、注销和通知观察者。

  2. 观察者(Observer):也称为订阅者或监听器,它定义了一个接口或抽象类,包含了观察者所需实现的方法,通常包括更新方法,在主题状态改变时被调用。

  3. 具体主题(Concrete Subject):实现主题接口或抽象类,具体主题维护自身状态,并在状态变化时通知观察者。

  4. 具体观察者(Concrete Observer):实现观察者接口或抽象类的具体类,它负责接收主题的通知并执行相应的操作。

观察者模式的优点在于解耦了主题和观察者之间的依赖关系,使得主题和观察者可以独立变化。当主题的状态发生改变时,所有观察者将被通知,从而实现了一种松耦合的方式来实现对象间的交互。

观察者模式广泛应用于许多场景,如事件处理、GUI开发、消息传递系统等。它提供了一种灵活的机制,使得对象之间能够及时响应和相互协作,同时也提高了代码的可维护性和可扩展性。

 

二、如何使用观察者模式

观察者模式是一种行为型设计模式,用于构建对象之间的一对多依赖关系。当一个对象(称为主题)的状态发生变化时,它会自动通知其所有依赖对象(称为观察者),以便它们可以做出相应的更新。

以下是一个使用Java实现观察者模式的简单示例代码:

首先,我们定义主题接口 Subject,其中包含了注册、注销和通知观察者的方法:

public interface Subject {
    void registerObserver(Observer observer);
    void unregisterObserver(Observer observer);
    void notifyObservers();
}

然后,我们定义观察者接口 Observer,其中包含了接收主题通知并进行相应操作的方法:

public interface Observer {
    void update();
}

接下来,我们实现具体的主题类 ConcreteSubject

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

public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private int state;

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        notifyObservers();
    }

    @Override
    public void registerObserver(Observer observer) {
        observers.add(observer);
    }

    @Override
    public void unregisterObserver(Observer observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}

最后,我们实现具体的观察者类 ConcreteObserver

public class ConcreteObserver implements Observer {
    private int observerState;
    private ConcreteSubject subject;

    public ConcreteObserver(ConcreteSubject subject) {
        this.subject = subject;
        this.subject.registerObserver(this);
    }

    @Override
    public void update() {
        observerState = subject.getState();
        System.out.println("Observer state updated: " + observerState);
    }
}

现在,我们可以使用这些类来演示观察者模式的工作方式:

public class Main {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();

        ConcreteObserver observer1 = new ConcreteObserver(subject);
        ConcreteObserver observer2 = new ConcreteObserver(subject);

        subject.setState(10);
        // 输出:
        // Observer state updated: 10
        // Observer state updated: 10

        subject.setState(20);
        // 输出:
        // Observer state updated: 20
        // Observer state updated: 20

        subject.unregisterObserver(observer2);

        subject.setState(30);
        // 输出:
        // Observer state updated: 30
    }
}

在上述示例中,我们创建了一个具体主题对象 subject 和两个具体观察者对象 observer1 和 observer2。当主题的状态发生变化时,它会通知所有注册的观察者,并调用其 update() 方法进行更新。

观察者模式使得主题与观察者之间松散耦合,使系统更灵活和可扩展。当我们需要在对象之间建立一对多的依赖关系,并实现对象状态的同步更新时,观察者模式是一个常用且强大的设计模式。

 

三、观察者模式的优势和使用场景

观察者模式是一种行为型设计模式,用于在对象之间建立一对多的依赖关系,当一个对象的状态发生变化时,其所有依赖对象都会自动收到通知并进行相应的更新。观察者模式具有以下优势和适用场景:

优势:

  1. 解耦:观察者模式将被观察者和观察者解耦,使它们可以独立地进行扩展和修改,而不会影响到彼此。
  2. 松散耦合:被观察者只需要知道观察者接口而不需要了解具体观察者的实现,从而降低了彼此之间的依赖程度,实现了松散耦合。
  3. 可重用性:观察者模式可增加新的观察者或被观察者,无需修改原有代码,提高了代码的可重用性。

使用场景:

  1. 当一个对象的改变需要同时通知其他多个对象,并且这些对象的更新操作可能不同步时,可以使用观察者模式。
  2. 当一个对象的状态变化需要引起其他相关对象的状态变化时,可以使用观察者模式来保持对象之间的一致性。
  3. 当系统中存在一个主体对象和多个观察者对象之间的动态关系,并且希望避免对象之间的紧耦合关系时,可以使用观察者模式。
  4. 当一个对象需要将自己的状态变化通知给一组观察者,同时这些观察者对象具有不同的行为和角色时,可以使用观察者模式。

总结来说,观察者模式适用于多个对象之间存在一对多的依赖关系,当一个对象的状态变化需要通知其他对象并进行相应处理时,观察者模式能够提供一种松散耦合的解决方案,增加系统的灵活性和可扩展性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/714301.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

三相交流电相序检测器/三相交流电相序指示器电路设计

三相交流电相序检测器 在使用三相交流电动机时&#xff0c;需要知道所连接三相电源的相序&#xff0c;若相序不正确&#xff0c;则电动机的旋转方向将与所需的相反&#xff0c;从而导致安全事故。本电路的功能为检测三相交流电源的相序 &#xff0c;并在相序正确的前提下自动接…

15 线程

文章目录 线程创建MFC使用CreateThread线程案例&#xff08;AfxBeginThread MFC 创建线程&#xff09;开始创建线程线程暂停继续结束线程全部代码 线程创建 #include <stdio.h> #include <Windows.h>//线程处理函数 //线程1 DWORD WINAPI DoWork1(LPVOID lpParame…

BOSHIDA DC电源模块在自动化设备的详细应用

BOSHIDA DC电源模块在自动化设备的详细应用 DC电源模块是自动化设备中经常使用的电源设备&#xff0c;它可以将交流电转换成稳定的直流电&#xff0c;以满足自动化设备的电能需求。以下是DC电源模块在自动化设备中的详细应用&#xff1a; 1. 逆变器控制器&#xff1a;DC电源模…

SciencePub学术 | 算法类重点SCIEEI征稿中

SciencePub学术 刊源推荐: 算法类重点SCI&EI征稿中&#xff01;2区闭源好刊&#xff0c;对国人非常友好。信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; 算法类重点SCI&EI 【期刊简介】IF&#xff1a;6.0-6.5&#xff0c;JCR2区&#xff0c;中…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)三:找回密码界面及对应功能实现

一、本章内容 本章实现找回密码功能,包括短信验证码找回、邮箱验证码找回等功能,并通过node-send-email发送邮箱验证码,实现找回密码界面、接口等功能。 1. 详细课程地址: 待发布 2. 源码下载地址: 待发布 二、界面预览 三、开发视频

cesium鹰眼效果实现(cesium自带方法)

具体思路是&#xff1a;新建一个viewer作为鹰眼地图&#xff0c;监听主地图的相机change事件&#xff0c;手动更新鹰眼地图的视角。 效果&#xff1a; 1. 创建一个id为hawkEyeMap的DOM节点&#xff0c;配置一下样式。 <div id"hawkEyeMap"></div>#hawkE…

在springboot项目做valid注解校验,但是对象是继承pojo(bean)的DTO类怎么办?

将校验注解直接添加到 DTO 类的字段上&#xff0c;而不是添加到父类中。修改 DTO 类的字段声明&#xff0c;将校验注解添加到字段上。例如 Data TableName("t_exam_oral") EqualsAndHashCode(callSuper true) ApiModel(value "ExamOral对象", descripti…

CANDENCE :简单贴装器件封装绘制

紧接candence:常见表贴焊盘绘制举例 简单贴装器件封装绘制 以0603封装电容为例&#xff0c;绘制其封装&#xff0c;这里会用到前面绘制的电容的焊盘。 1、打开PCB editor 软件工具 2、新建一个PACKGE symbol 文件,设置好路径和名称。点击ok确认 3、设置画布尺寸、原点位置、…

四、构建高可用的 Eureka-Server 集群

5.1 对刚才的 eureka-server 修改配置文件 5.1.1 server-1 server:port: 8761 #为什么是 8761&#xff0c;其他端口就报错spring:application:name: eureka-server #服务名称eureka:client:fetch-registry: true #是否拉取服务列表register-with-eureka: true #是否注册自己&…

《PyTorch深度学习实践》第十一讲 循环神经网络(基础篇 + 高级篇)

b站刘二大人《PyTorch深度学习实践》课程第十一讲循环神经网络&#xff08;基础篇 高级篇&#xff09;笔记与代码&#xff1a; https://www.bilibili.com/video/BV1Y7411d7Ys?p12&vd_sourceb17f113d28933824d753a0915d5e3a90 https://www.bilibili.com/video/BV1Y7411d7Y…

netty学习(3):SpringBoot整合netty实现多个客户端与服务器通信

1. 创建SpringBoot父工程 创建一个SpringBoot工程&#xff0c;然后创建三个子模块 整体工程目录&#xff1a;一个server服务&#xff08;netty服务器&#xff09;&#xff0c;两个client服务&#xff08;netty客户端&#xff09; pom文件引入netty依赖&#xff0c;springboot…

国企一面会问什么?

前言&#xff1a; \textcolor{Green}{前言&#xff1a;} 前言&#xff1a; &#x1f49e;快秋招了&#xff0c;那么这个专栏就专门来记录一下&#xff0c;同时呢整理一下常见面试题 &#x1f49e;部分题目来自自己的面试题&#xff0c;部分题目来自网络整理 国企注重的和私企会…

中国各地区新能源汽车产量(2015-2022年) 共13个指标

从各地区统计公报、各地区统计年鉴整理了69个省市的新能源汽车产量数据&#xff0c;并提供了包含原始数据的各个来源。数据显示&#xff0c;中国各地区的新能源汽车产量存在着明显的区域差异。该数据可为各研究人员提供重要参考&#xff0c;有助于制定地方产业发展规划和市场战…

ruoyi-vue | electron打包教程(超详细)

公司项目由于来不及单独做客户端了&#xff0c;所以想到用electron直接将前端打包程exe,dmg等格式的安装包。 由于使用的ruoyi-vue框架开发&#xff0c;所以这篇教程以ruoyi-vue为基础的。 环境说明 nodejs&#xff1a;v16.18.1npm&#xff1a;8.19.2ruoyi-vue&#xff1a;3.8…

基于SQLI的SQL字符型报错注入

基于SQLI的SQL字符型报错注入 一. 实验目的 理解数字型报错SQL注入漏洞点的定位方法&#xff0c;掌握利用手工方式完成一次完整SQL注入的过程&#xff0c;熟悉常见SQL注入命令的操作。 二. 实验环境 渗透主机&#xff1a;KALI平台 用户名: college 密码: 360College 目标网…

Windows 10 执行wsl命令报错: --list -o命令行选项无效 --update命令行选项无效等解决办法

问题说明 在使用wsl命令的时候&#xff0c;wsl --update&#xff0c;wsl --list -o等关键的命令都显示命令行选项无效 但是wsl这个命令却又是一个有效的命令 解决办法 1.卸载旧版本的WSL 没有子系统可以跳过这个步骤 打开命令提示符或PowerShell窗口&#xff08;以管理员身…

深蓝学院C++基础与深度解析笔记 第 10 章 泛型算法与 Lambda 表达式

第 10 章 泛型算法与 Lambda 表达式 1. 泛型算法 1.1 泛型算法&#xff1a; 可以支持多种类型的算法。 int x[100]; std::sort(std: : begin(x), std : :end(x));1.11 这里重点讨论 C 标准库中定义的算法&#xff1a; <algorithm > <numeric> <ranges> 1.…

简洁清新后台模板推荐(光年)

目录 前言一、后台模板介绍1.作者介绍2.模板介绍 二、界面展示1.登录2.首页3.UI元素4.表单5.工具类6.示例页面7.主题选择 三、入口总结 前言 作为后端开发人员&#xff0c;前端技术确实不精通&#xff0c;也没有太多的精力搞前端。所以一直在搜寻一些现成的模板。最近发现一个…

基于单片机的盲人导航智能拐杖老人防丢防摔倒发短息定位

功能介绍 以STM32单片机作为主控系统&#xff1b; OLED液晶当前实时距离&#xff0c;安全距离&#xff0c;当前经纬度信息&#xff1b;超声波检测小于设置的安全距离&#xff0c;蜂鸣器报警提示&#xff1a;低于安全距离&#xff01;超声波检测当前障碍物距离&#xff0c;GPS进…

Linux-CentOS7版本的系统搭建达梦数据库

目录 VMware中安装CentOS 7.5并做相关的配置搭建Docker环境搭建达梦数据库拉取镜像查看镜像命令为镜像设置一个别名根据镜像 创建一个容器 根据镜像 创建一个容器启动并进入容器 VMware中安装CentOS 7.5并做相关的配置 使用VMware安装CentOS7的虚拟机可以参考另外一篇文章&…