从业务场景学习观察者模式

在开发中,当一个对象状态发生变化,需要通知多个其他对象时,观察者模式是一个非常有效的设计模式。通过使用观察者模式,可以在对象间建立一种松散的依赖关系,使得对象在状态变化时,可以通知到其他依赖于它的对象进行相应的更新。本文将以商品库存变化通知的场景为例,带你了解观察者模式的应用。

观察者模式概述

观察者模式(Observer Pattern)是一种行为型设计模式,用于定义对象间一对多的依赖关系。当一个对象(即被观察者主题 )的状态发生变化时,所有依赖于它的对象(即观察者)都会收到通知并更新。

观察者模式还有以下几个别名:

  • 发布-订阅(Publish-Subscribe)模式:被观察者发布消息,观察者订阅消息;
  • 模型-视图(Model-View)模式:在 MVC 架构中,Model 的变化通知 View;
  • 源-监听(Source-Listener)模式:被观察者作为消息源,观察者作为消息监听者。

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

假设在一个电子商务系统中,有多个模块依赖于商品的库存信息。比如,当商品库存数量发生变化时,我们希望商品详情页和购物车的库存信息也能同步更新,以便向用户展示最新的库存状态。使用观察者模式可以很好地解决这种需求。

在这个场景中:

  • 商品库存(Product) 是被观察者;
  • 商品详情页(ProductDetailPage)购物车(ShoppingCart) 是观察者,它们需要在商品库存变化时收到通知并更新显示。

实现观察者模式

1. 定义观察者接口

首先,我们定义一个 Observer 接口,包含一个 update 方法。当被观察者状态改变时,这个方法会被调用,更新观察者的状态。

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

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

接下来,我们定义商品类 Product,实现以下功能:

  • 维护观察者列表:可以添加、移除观察者;
  • 通知观察者:当库存数量发生变化时,通知所有观察者更新库存显示。
java 复制代码
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. 实现具体观察者(商品详情页和购物车)

现在,我们定义两个具体的观察者类------商品详情页 ProductDetailPage 和购物车 ShoppingCart,实现 Observer 接口,在库存变化时更新各自的显示信息。

java 复制代码
// 商品详情页观察者(Concrete Observer)
class ProductDetailPage implements Observer {
    @Override
    public void update(int stockQuantity) {
        System.out.println("商品详情页更新库存显示为: " + stockQuantity);
    }
}

// 购物车观察者(Concrete Observer)
class ShoppingCart implements Observer {
    @Override
    public void update(int stockQuantity) {
        System.out.println("购物车更新库存显示为: " + stockQuantity);
    }
}

4. 测试观察者模式

最后,我们创建一个测试类 ObserverPatternExample,验证当商品库存发生变化时,商品详情页和购物车都能收到通知。

java 复制代码
public class ObserverPatternExample {
    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);
    }
}

运行结果

运行代码后,我们可以看到商品库存发生变化时,所有注册的观察者都收到了通知并更新了库存信息。

plaintext 复制代码
商品库存更新为: 10
商品详情页更新库存显示为: 10
购物车更新库存显示为: 10
商品库存更新为: 5
商品详情页更新库存显示为: 5
购物车更新库存显示为: 5

代码解读

  1. 被观察者 (Product) :当库存数量通过 setStockQuantity 方法被修改时,会触发 notifyObservers 方法,通知所有观察者更新状态。
  2. 观察者 (Observer) :通过实现 Observer 接口的 update 方法,各观察者可以响应库存变化,更新各自的库存显示。
  3. 松散耦合 :观察者模式让被观察者和观察者之间是松散耦合的,被观察者只知道观察者实现了 Observer 接口,而不关心其具体实现。这种设计提高了代码的可扩展性和可维护性。

观察者模式的优势

  • 松散耦合:观察者和被观察者之间只通过接口依赖,减少了对象之间的耦合度。
  • 扩展性强:可以动态添加或移除观察者,且不影响被观察者的实现。
  • 灵活性:在运行时可以灵活注册和通知观察者。

观察者模式的应用场景

  • 事件系统:在事件驱动编程中,常使用发布-订阅模式来处理事件。
  • MVC 架构:在 MVC 模式中,Model 是被观察者,View 是观察者,当 Model 数据变化时,View 自动更新。
  • 消息通知系统:如订单系统中的订单状态变化通知、库存更新通知等。

总结

观察者模式在应用程序中非常实用,尤其是当对象间的状态依赖关系频繁发生时。本文通过商品库存更新的示例演示了如何实现观察者模式,从而在商品状态变化时及时通知商品详情页和购物车更新显示。这种设计模式让系统更具扩展性和灵活性,是我们在复杂应用中实现模块解耦的有效方式。

相关推荐
汤姆和佩琦29 分钟前
2024-12-25-sklearn学习(20)无监督学习-双聚类 料峭春风吹酒醒,微冷,山头斜照却相迎。
学习·聚类·sklearn
好学近乎知o40 分钟前
正则表达式(学习Django过程中可能涉及的)
学习·正则表达式·django
雨中奔跑的小孩43 分钟前
爬虫学习案例8
爬虫·学习
jieshenai1 小时前
使用 VSCode 学习与实践 LaTeX:从插件安装到排版技巧
ide·vscode·学习
灰太狼不爱写代码4 小时前
CUDA11.4版本的Pytorch下载
人工智能·pytorch·笔记·python·学习
eybk9 小时前
Pytorch+Mumu模拟器+萤石摄像头实现对小孩学习的监控
学习
6.949 小时前
Scala学习记录 递归调用 练习
开发语言·学习·scala
守护者17011 小时前
JAVA学习-练习试用Java实现“使用Arrays.toString方法将数组转换为字符串并打印出来”
java·学习
学会沉淀。11 小时前
Docker学习
java·开发语言·学习
Rinai_R11 小时前
计算机组成原理的学习笔记(7)-- 存储器·其二 容量扩展/多模块存储系统/外存/Cache/虚拟存储器
笔记·物联网·学习