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

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

什么是观察者模式

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

观察者模式的优点

  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
相关推荐
想努力找到前端实习的呆呆鸟1 小时前
网易云桌面端--精选歌单布局思路记录
前端·javascript·vue.js
用户93816912553601 小时前
Head First 模板方法模式
设计模式
进击的尘埃4 小时前
策略模式和状态模式到底啥区别?拿审批流表单说个明白
javascript
专业抄代码选手4 小时前
在react中,TSX是如何转变成JS的
前端·javascript
进击的尘埃5 小时前
SOLID 原则在 React 组件库里怎么落地:五个重构案例
javascript
本末倒置1835 小时前
Bun 内置模块全解析:告别第三方依赖,提升开发效率
前端·javascript·node.js
是糖糖啊5 小时前
OpenSpec 完整使用流程笔记 (SDD)
设计模式
进击的尘埃5 小时前
中介者模式:把面板之间的蜘蛛网拆干净
javascript
Hilaku6 小时前
OpenClaw 很爆火,但没人敢聊它的权限安全🤷‍♂️
前端·javascript·程序员
兆子龙7 小时前
React Native 完全入门:从原理到实战
前端·javascript