观察者模式 vs 不使用观察者模式:商品库存变化的通知

在软件开发中,观察者模式是一种非常常见的设计模式,用于解决对象间的依赖关系。当一个对象的状态发生改变时,需要通知其他相关对象,确保它们的状态也随之更新。本文将通过一个具体的业务场景——商品库存变化,来对比在使用和不使用观察者模式时的实现方式,从而帮助你更好地理解观察者模式的优势。

业务场景:商品库存变化通知

假设我们正在开发一个电商系统,其中涉及到多个模块对商品库存信息的依赖:

  • 商品详情页:展示商品的库存数量。
  • 购物车:展示用户购物车中商品的库存状态。

当商品库存数量发生变化时,我们需要通知这些模块进行同步更新。如果不使用观察者模式,可能会导致代码耦合性较强,难以扩展和维护。而使用观察者模式,则能提供一个解耦的设计,使得各个模块之间的通信更加简洁和高效。

不使用观察者模式

1. 直接调用更新方法

在没有观察者模式的情况下,当商品库存发生变化时,我们可能会直接在商品类中手动调用商品详情页和购物车的更新方法。这会导致商品类和其他模块(商品详情页、购物车)之间存在紧密的耦合。

// 商品类(没有观察者模式)
class Product {private int stockQuantity;  // 库存数量private ProductDetailPage detailPage;private ShoppingCart shoppingCart;public Product(ProductDetailPage detailPage, ShoppingCart shoppingCart) {this.detailPage = detailPage;this.shoppingCart = shoppingCart;}// 设置库存数量并更新其他模块public void setStockQuantity(int stockQuantity) {this.stockQuantity = stockQuantity;System.out.println("商品库存更新为: " + stockQuantity);// 手动通知商品详情页和购物车更新库存detailPage.update(stockQuantity);shoppingCart.update(stockQuantity);}
}

2. 商品详情页和购物车

商品详情页和购物车类会有一个 update 方法,用于接收商品库存的变化并更新显示。

// 商品详情页
class ProductDetailPage {public void update(int stockQuantity) {System.out.println("商品详情页更新库存显示为: " + stockQuantity);}
}// 购物车
class ShoppingCart {public void update(int stockQuantity) {System.out.println("购物车更新库存显示为: " + stockQuantity);}
}

3. 测试类

在这个例子中,我们直接在商品类中管理了商品详情页和购物车的更新逻辑。

public class WithoutObserverPattern {public static void main(String[] args) {ProductDetailPage detailPage = new ProductDetailPage();ShoppingCart shoppingCart = new ShoppingCart();Product product = new Product(detailPage, shoppingCart);product.setStockQuantity(10);product.setStockQuantity(5);}
}

运行结果

商品库存更新为: 10
商品详情页更新库存显示为: 10
购物车更新库存显示为: 10
商品库存更新为: 5
商品详情页更新库存显示为: 5
购物车更新库存显示为: 5

存在的问题

  1. 耦合性强:商品类直接依赖于商品详情页和购物车,若以后新增其他依赖库存信息的模块,需要修改商品类,违反了开闭原则(OCP)。
  2. 扩展困难:若有多个模块依赖库存变化,每个模块都需要在商品类中手动注册,增加了维护难度。
  3. 难以维护:随着项目的增长,代码会变得越来越复杂,修改其中的一个部分可能会引发连锁反应,增加出错的风险。

使用观察者模式

1. 观察者接口

首先,我们定义观察者接口 Observer,其中包含一个 update 方法,用于接收商品库存变化的通知。

// 定义观察者接口
interface Observer {void update(int stockQuantity);  // 更新库存数量的方法
}

2. 被观察者类(商品类)

接下来,我们定义商品类 Product,它会维护一个观察者列表,并在库存变化时通知所有观察者。

import java.util.ArrayList;
import java.util.List;// 定义被观察的商品类(Subject)
class Product {private List<Observer> observers = new ArrayList<>();  // 观察者列表private int stockQuantity;  // 库存数量// 添加观察者public void addObserver(Observer observer) {observers.add(observer);}// 移除观察者public void removeObserver(Observer observer) {observers.remove(observer);}// 通知所有观察者private void notifyObservers() {for (Observer observer : observers) {observer.update(stockQuantity);  // 更新每个观察者}}// 设置库存数量,并通知观察者public void setStockQuantity(int stockQuantity) {this.stockQuantity = stockQuantity;System.out.println("商品库存更新为: " + stockQuantity);notifyObservers();  // 通知所有观察者}
}

3. 具体观察者类(商品详情页和购物车)

商品详情页和购物车分别实现观察者接口,当商品库存变化时,它们会接收到更新通知,并更新各自的库存显示。

// 商品详情页(观察者)
class ProductDetailPage implements Observer {@Overridepublic void update(int stockQuantity) {System.out.println("商品详情页更新库存显示为: " + stockQuantity);}
}// 购物车(观察者)
class ShoppingCart implements Observer {@Overridepublic void update(int stockQuantity) {System.out.println("购物车更新库存显示为: " + stockQuantity);}
}

4. 测试类

在测试类中,我们通过 addObserver 方法将商品详情页和购物车添加为观察者,商品库存更新时,它们会自动接收到通知并更新显示。

public class WithObserverPattern {public static void main(String[] args) {Product product = new Product();ProductDetailPage detailPage = new ProductDetailPage();ShoppingCart shoppingCart = new ShoppingCart();// 注册观察者product.addObserver(detailPage);product.addObserver(shoppingCart);// 设置库存数量,通知观察者product.setStockQuantity(10);product.setStockQuantity(5);}
}

运行结果

商品库存更新为: 10
商品详情页更新库存显示为: 10
购物车更新库存显示为: 10
商品库存更新为: 5
商品详情页更新库存显示为: 5
购物车更新库存显示为: 5

优势

  1. 低耦合性:商品类和观察者类之间只通过接口进行依赖,任何一个模块的变化不会影响到其他模块的实现。
  2. 可扩展性强:当需要增加新的依赖商品库存的模块时,只需实现 Observer 接口并注册为观察者,无需修改商品类。
  3. 符合开闭原则:商品类可以在不修改的情况下增加新的观察者,保持代码的稳定性。

对比总结

特性不使用观察者模式使用观察者模式
耦合性高,商品类直接依赖多个模块(商品详情页、购物车等)低,商品类只依赖于 Observer 接口
扩展性差,增加新模块需要修改商品类好,新增模块只需实现观察者接口并注册即可
维护性差,修改商品类可能导致其他模块发生问题好,模块独立,修改不会影响其他模块
符合设计原则不符合开闭原则符合开闭原则

结论

通过对比可以看出,观察者模式解决了不使用观察者模式时存在的耦合性高、扩展性差的问题,使得系统更加灵活、可维护和可扩展。在需要处理多个模块之间的依赖关系时,观察者模式提供了一种简洁且有效的方式来解耦不同模块之间的关系。
说点大白话就是采用观察者模式是定义了一个统一的接口,不同的观察者都实现这个接口。然后在被观察的目标中维护一个观察者的集合,若是有改变则指需要增加或者删除对应的观察者即可

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

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

相关文章

div加4个角边框 css

效果&#xff1a; :root {--corner-color: #4ba7f5; } .data-item {position: relative;width: 100px;height: 60px;overflow: hidden;background: linear-gradient(to left, var(--corner-color), var(--corner-color)) left top no-repeat,linear-gradient(to bottom, var(-…

108. UE5 GAS RPG 实现地图名称更新和加载关卡

在这一篇里&#xff0c;我们将实现对存档的删除功能&#xff0c;在删除时会有弹框确认。接着实现获取玩家的等级和地图名称和存档位置&#xff0c;我们可以通过存档进入游戏&#xff0c;玩家在游戏中可以在存档点存储存档。 实现删除存档 删除存档需要一个弹框确认&#xff0…

CAN编程示例之socket CAN

socket CAN概念 socketcan子系统是在Linux下CAN协议(Controller Area Network)实现的一种实现方法。 CAN是一种在世界范围内广泛用于自动控制、嵌入式设备和汽车领域的网络技术。Linux下最早使用CAN的方法是基于字符设备来实现的&#xff0c;与之不同的是Socket CAN使用伯克利…

如何使用.bat实现检测电脑网络连接是否正常?

1、在电脑桌面新建一个记事本文档&#xff0c;将如下内容写进去&#xff1a; echo 正在检查中...echo off ping www.baidu.com -t pause:: 这是注释2、然后&#xff0c;保存一下&#xff0c;再把桌面此文件重命名为检查电脑外网连接.bat 3、双击此程序&#xff0c;可以检测…

C#高级:使用Invoke关键字通过 Type 类型调用指定的方法

demo如下&#xff1a; using System.Reflection; using System;public class Program {public class Calculator{public int Add(int a, int b){return a b;}}public class Student{public string Name { get; set; }}public class Example{// 泛型方法public string Generi…

VTK知识学习(8)-坐标系统

1、概述 计算机图形学里常用的坐标系统有4种&#xff1a; 1&#xff09;、Model坐标系统。定义模型时所采用的坐标系统&#xff0c;通常是局部的笛卡儿坐标系。 2&#xff09;、World坐标系统。是放置Actor的三维空间坐标系。 Actor&#xff08;vtkActor类&am…

MongoDB新版本安装配置教程(7.0.15版本-zip下载)

找了半天MongoDB新版本怎么解决没有mongo命令,都没有很好的解决方法 现在分享一下: 首先下载: 然后手动创建 data 和 log 两个文件夹 然后再系统变量配置环境变量 在data的目录下&#xff0c;创建一个db文件 然后:在bin目录下cmd执行: mongod --dbpath D:\MongoDB\data\db …

在Docker环境下为Nginx配置HTTPS

前言 配置HTTPS已经成为网站部署的必要步骤。本教程将详细介绍如何在Docker环境下为Nginx配置HTTPS&#xff0c;使用自签名证书来实现加密通信。虽然在生产环境中建议使用权威CA机构颁发的证书&#xff0c;但在开发测试或内网环境中&#xff0c;自签名证书是一个很好的选择。 …

QEMU 模拟器中运行的 Linux 系统

这两个文件通常用于在 QEMU 模拟器中运行的 Linux 系统&#xff0c;具体作用如下&#xff1a; 1. linux-aarch64-qemu.ext4&#xff1a; - **文件类型**&#xff1a;这是一个文件系统镜像文件&#xff0c;通常是 ext4 文件系统格式。 - **作用**&#xff1a;它包含了 Li…

Struts扫盲

Struts扫盲 这里的struts是struts1。以本文记录我的那些复习JavaEE的痛苦并快乐的晚上 Struts是什么 框架的概念想必大家都清楚&#xff0c;框架即“半成品代码”&#xff0c;是为了简化开发而设计的。一个项目有许多分层&#xff0c;拿一个MVC架构的Web应用来说&#xff0c;有…

【论文精读】GOT-OCR2.0源码论文——打破传统OCR流程的多模态视觉-语言大模型架构:预训练VitDet 视觉模型+ 阿里通义千问Qwen语言模型

作为本系列的开篇文章&#xff0c;首先定下本系列的整体基调。论文精读系列&#xff0c;旨在记录研读深度学习、强化学习相关论文的个人心得和理解&#xff0c;仅供参考&#xff0c;欢迎指正错误和研究探讨。 所有文章只会摘选论文部分进行分析&#xff0c;且不一定按原文行文顺…

【Rust 编程语言工具】rustup-init.exe 安装与使用指南

rustup-init.exe 是用于安装和管理 Rust 编程语言工具链的 Windows 可执行文件。Rust 是一种系统级编程语言&#xff0c;旨在提供安全、并发和高性能的功能。rustup-init.exe 是官方提供的安装器&#xff0c;用于将 Rust 安装到 Windows 操作系统中&#xff0c;并配置相关环境。…

【Hutool系列】反射工具-ReflectUtil

前言 反射是 Java 中一种强大的机制&#xff0c;可以在运行时动态地获取类的信息并操作类的属性和方法。在 Java 中&#xff0c;通过反射可以获取和设置类的字段、调用类的方法、创建类的实例等。Java的反射机制&#xff0c;可以让语言变得更加灵活&#xff0c;对对象的操作也更…

Microsoft Fabric - 尝试一下Real time event stream

1. 简单介绍 微软推出的Microsoft Fabric平台已经有一段时间了&#xff0c;这是一个Data engineer, Data Sciencist, Business等多种工作角色的人员可以一起工作的一个大平台。 note, Microsoft Fabric 提出了OneLake, LakeHouse的概念&#xff0c;同时为了防止数据冗余&#…

数字图像处理(c++ opencv):图像复原与重建-常见的滤波方法--自适应滤波器

自适应局部降噪滤波器 自适应局部降噪滤波器&#xff08;Adaptive, Local Noise Reduction Filter&#xff09;原理步骤 步骤 &#xff08;1&#xff09;计算噪声图像的方差 &#xff1b; &#xff08;2&#xff09;计算滤波器窗口内像素的均值 和方差 &#xff1b; &…

C++:类和对象(上)

目录 一、类的定义 二、 访问限定符 三、 实例化概念类&#xff1a; 类&#xff08;Class&#xff09; 对象&#xff08;Object&#xff09; 实例化&#xff08;Instantiation&#xff09; 四、 对象大小 五、this 指针的基本概念 this 指针的作用&#xff1a; this 指…

如何在vscode 中打开新文件不覆盖上一个窗口

在 VSCode 中&#xff0c;如果你单击文件时出现了覆盖Tab的情况&#xff0c;这通常是因为VSCode默认开启了预览模式。在预览模式下&#xff0c;单击新文件会覆盖当前预览的文件Tab。为了解决这个问题&#xff0c;你可以按照以下步骤进行操作 1.打开VSCode&#xff1a;启动你的…

Linux篇(权限管理命令)

目录 一、权限概述 1. 什么是权限 2. 为什么要设置权限 3. Linux中的权限类别 4. Linux中文件所有者 4.1. 所有者分类 4.2. 所有者的表示方法 属主权限 属组权限 其他权限 root用户&#xff08;超级管理员&#xff09; 二、普通权限管理 1. ls查看文件权限 2. 文件…

冲压车间如何开展六西格玛管理培训

面对日益严苛的客户要求与成本控制挑战&#xff0c;传统的管理模式已难以满足高质量发展的需求。此时&#xff0c;六西格玛管理以其严谨的数据驱动、持续改进的理念&#xff0c;成为众多企业转型升级的有力工具。本文&#xff0c;天行健企业管理咨询公司将深入探讨冲压车间如何…

基于微信小程序的平安驾校预约平台的设计与实现(源码+LW++远程调试+代码讲解等)

摘 要 互联网发展至今&#xff0c;广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对高校教师成果信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#xff0c;劳动强度大&#xff0c;费时费力…