实现解耦:观察者模式的应用

观察者模式,开始接触开发的时候,就有使用到。某个值的变化,引起其他值也发生变化。这个是使用比较多的设计模式。掌握该设计模式,对开发而言是比较重要得。今天,就对该设计模式进行分析

什么是观察者模式

观察者模式:定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

观察者模式的优点

  1. 降低耦合性:观察者模式允许主题和观察者之间解耦,因为它们之间只存在抽象的观察者接口,而不存在直接的依赖关系。
  2. 增加可扩展性:观察者模式使得添加新的观察者变得容易,只需要实现观察者接口并注册到主题即可。
  3. 提高系统灵活性:观察者模式使得主题和观察者之间的通信变得灵活,可以根据需要实现推送或拉取信息的功能。

模式UML

观察者模式包含如下角色:

  • Subject: 目标
  • ConcreteSubject: 具体目标
  • Observer: 观察者
  • ConcreteObserver: 具体观察者

从UML图中,可以看出,在抽象类Subject中,通过attach将观察者加入objList中。ConcreteSubject对象中,在被观察的对象变更时,通知objList中的观察者。以达到对目标变化的监听。核心在于objList的观察者存储,与ConcreteSubject属性变化的通知。

javascript 实现

JAVASCRIPT 复制代码
let Subject = function () {
        this.objlist = []
    }

    Subject.prototype.attach = function (pObeserver) {
        this.objlist.push(pObeserver);
    }

    Subject.prototype.detach = function () {
        throw (new Error("子类必须实现此方法"))
    }

    Subject.prototype.notify = function () {
        throw (new Error("子类必须实现此方法"))
    }

    let ConcreteSubject = function () {
        Subject.apply(this, arguments)
    }
    ConcreteSubject.prototype = Object.create(Subject.prototype)
    ConcreteSubject.prototype.constructor = ConcreteSubject

    ConcreteSubject.prototype.attach = function (pObeserver) {
        this.objlist.push(pObeserver);
    }

    Subject.prototype.detach = function (pObeserver) {

        for (let index = 0; index < this.objlist.length; index++) {
            const element = this.objlist[index];
            if (element == pObeserver) {
                this.objlist.splice(index, 1)
                return
            }
        }

    }

    Subject.prototype.notify = function () {
        this.objlist.forEach(obj => {
            obj.update(this)
        });
    }

    ConcreteSubject.prototype.setState = function (state) {
        this.state = state;
        this.notify()
    }

    ConcreteSubject.prototype.getState = function () {
        return this.state
    }


    let Obsever = function () {}
    Obsever.prototype.update = function () {
        throw (new Error("子类必须实现此方法"))
    }

    let ConcreteObsever = function (name) {
        this.name = name
        this.obeserverState = ""
    }
    ConcreteObsever.prototype = Object.create(Obsever.prototype)
    ConcreteObsever.prototype.constructor = ConcreteObsever
    ConcreteObsever.prototype.update = function (sub) {
        this.obeserverState = sub.getState()

        console.log("收到" + this.name + "状态更新为:" + this.obeserverState);
    }

    let _ConcreteSubject = new ConcreteSubject();
    let _ConcreteObseverA = new ConcreteObsever("观察者A");
    let _ConcreteObseverB = new ConcreteObsever("观察者B");

    _ConcreteSubject.attach(_ConcreteObseverA)
    _ConcreteSubject.attach(_ConcreteObseverB)

    _ConcreteSubject.setState(1)
    // 收到观察者A状态更新为:1
    // 收到观察者B状态更新为:1

    _ConcreteSubject.detach(_ConcreteObseverB)
    _ConcreteSubject.setState(2)
    // 收到观察者A状态更新为:2
相关推荐
researcher-Jiang9 小时前
Design Patterns——Template Method入门到情景实战
python·设计模式·模板方法模式
多加点辣也没关系11 小时前
JavaScript|第4章:类型转换
开发语言·javascript
yqcoder11 小时前
httpOnly 是什么,又有什么用?
开发语言·前端·javascript
烬羽12 小时前
还在手动拼路径、写回调地狱?一文吃透 Node.js 的 path 和 fs
javascript·程序员·node.js
mONESY12 小时前
LangChain JS 高性能并行执行解析、工具调用底层封装
javascript
迅速的自行车13 小时前
从一段模板说起
前端·javascript·vue.js
YIAN13 小时前
LangChain JS 工具调用实战:基于 DeepSeek-V4-Flash 实现本地文件读取 AI 代码助手(完整可运行源码)
javascript·langchain·前端框架
尼斯湖皮皮怪13 小时前
iceCoder 记忆系统深度分析
前端·javascript
爸爸61914 小时前
07 ArkTS 基础类型与接口定义:从 TypeScript 到鸿蒙的类型升级
javascript·华为·typescript·harmonyos·鸿蒙系统
默_笙15 小时前
🌏 MCP 是 AI 界的 USB-C:一个协议让所有模型都能用上所有工具
前端·javascript