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

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

什么是观察者模式

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

观察者模式的优点

  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
相关推荐
極光未晚15 分钟前
JavaScript 中 this 指向的全面解析
javascript
99乘法口诀万物皆可变26 分钟前
C#设计模式之AbstractFactory_抽象工厂_对象创建新模式-练习制作PANL(一)
服务器·javascript·c#·html
charlie11451419138 分钟前
从C++编程入手设计模式——装饰器模式
c++·设计模式·装饰器模式
@PHARAOH43 分钟前
WHAT - React Native 开发 App 从 0 到上线全流程周期
javascript·react native·react.js
集成显卡1 小时前
图片压缩工具 | Electron应用配合 commander 提供命令行调用功能
前端·javascript·electron·人机交互·命令行·cmd
我是来人间凑数的1 小时前
electron 嵌入web网页的三种方式
前端·javascript·electron
天上掉下来个程小白1 小时前
Apache ECharts-01.介绍
前端·javascript·spring boot·apache·苍穹外卖
夜空孤狼啸1 小时前
前端常用拖拽组件库(vue3、react、vue2)
前端·javascript·react.js·typescript·前端框架·vue3
嘗_2 小时前
暑期前端训练day1
前端·javascript·八股文·手撕代码
可可格子衫2 小时前
129. 求根节点到叶节点数字之和 --- DFS +回溯(js)
javascript·算法·深度优先