您的位置:

JS观察者模式

一、JS观察者模式和发布订阅

JS观察者模式和发布订阅模式都属于一种基于事件的设计模式,而且代码实现上其实也差不多。最重要的区别在于在观察者模式中,观察者知道被观察对象的存在,而在发布订阅模式中,发布者和订阅者相互独立,互相不知道对方的存在。

举个例子,在一个页面中有一个订阅按钮,我们在点击按钮时需要做两件事情:一是执行具体的订阅逻辑,二是在适当的时候通知其他需要收到通知的部分。在发布订阅模式中,我们会建立一个事件中心,让订阅者在其中注册自己感兴趣的事件,而发布者发布事件时,则会告知事件中心,事件中心再把事件推送给订阅者;而在观察者模式中,我们则会新建一个对象,作为被观察的目标,它会持有所有需要接收通知的观察者的引用,当目标发生变化时,就会直接通知观察者。

/* 发布订阅模式 */
const Event = new Vue();

// 订阅者A
Event.$on('subscribe', () => {
    console.log('subscribe');
});

// 发布者
Event.$emit('subscribe');
/* 观察者模式 */
class Subject {
    constructor() {
        this.observers = [];
    }

    addObserver(observer) {
        this.observers.push(observer);
    }

    removeObserver(observer) {
        const index = this.observers.indexOf(observer);
        if (index >= 0) {
            this.observers.splice(index, 1);
        }
    }

    notifyObservers() {
        for (let observer of this.observers) {
            observer.update();
        }
    }
}

class Observer {
    constructor(name) {
        this.name = name;
    }

    update() {
        console.log(`${this.name} has been notified.`);
    }
}

const subject = new Subject();
const observer1 = new Observer('Observer1');
const observer2 = new Observer('Observer2');

// 添加观察者
subject.addObserver(observer1);
subject.addObserver(observer2);

// 通知观察者
subject.notifyObservers();

二、JS观察者模式 阮一峰

JS观察者模式是基于发布订阅模式的一种设计模式,在JS中比较常见,对象间的一种依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都将得到通知。观察者模式提供了一种对象设计,让主题和观察者之间松耦合,以增强应用的可重用性和可扩展性。

阮一峰老师在他的JavaScript设计模式一书中给出了一个经典的例子,展示了观察者模式的用法,我们可以通过代码实现了解它的工作原理。

/* 发布者 */
class Subject {
    constructor() {
        this.observers = [];
    }

    addObserver(observer) {
        this.observers.push(observer);
    }

    removeObserver(observer) {
        const index = this.observers.indexOf(observer);
        if (index >= 0) {
            this.observers.splice(index, 1);
        }
    }

    notifyObservers() {
        for (let observer of this.observers) {
            observer.update();
        }
    }
}

/* 观察者 */
class Observer {
    constructor(name) {
        this.name = name;
    }

    update() {
        console.log(`${this.name} has been notified.`);
    }
}

const subject = new Subject();
const observer1 = new Observer('Observer1');
const observer2 = new Observer('Observer2');

// 添加观察者
subject.addObserver(observer1);
subject.addObserver(observer2);

// 通知观察者
subject.notifyObservers();

三、JS观察者模式怎么写

JS观察者模式在实现上比较简单,首先我们需要定义一个目标对象,它可以拥有多个观察者对象,并且能够在变化时通知所有观察者。观察者对象则需要定义一个update()方法,以响应目标对象的通知。

/* 定义目标对象 */
class Subject {
    constructor() {
        this.observers = [];
    }

    addObserver(observer) {
        this.observers.push(observer);
    }

    removeObserver(observer) {
        const index = this.observers.indexOf(observer);
        if (index >= 0) {
            this.observers.splice(index, 1);
        }
    }

    notifyObservers() {
        for (let observer of this.observers) {
            observer.update();
        }
    }

    /* 触发变化 */
    triggerChange() {
        // do something...
        // ...
        // 让所有观察者知道变化
        this.notifyObservers();
    }
}

/* 定义观察者对象 */
class Observer {
    constructor(name) {
        this.name = name;
    }

    update() {
        console.log(`${this.name} has been notified.`);
    }
}

const subject = new Subject();
const observer1 = new Observer('Observer1');
const observer2 = new Observer('Observer2');

// 添加观察者
subject.addObserver(observer1);
subject.addObserver(observer2);

// 执行变化
subject.triggerChange();

四、JS观察者模式的实现

JS观察者模式的实现过程中,需要注意以下几点:

1. 借助ES6的class语法,更易于描述出观察者和目标对象之间的关系。

2. 目标对象需要维护一个观察者数组,通过addObserver()方法添加观察者,并通过removeObserver()方法将不在需要通知的观察者移除。

3. 观察者必须拥有update()方法,以响应目标对象的通知。在Notify()函数中,所有的观察者都会被遍历,并逐个执行它们的update()函数。

/* 目标对象类 */
class Subject {
    constructor() {
        this.observers = [];
    }

    addObserver(observer) {
        this.observers.push(observer);
    }

    removeObserver(observer) {
        const index = this.observers.indexOf(observer);
        if (index >= 0) {
            this.observers.splice(index, 1);
        }
    }

    notifyObservers() {
        for (let observer of this.observers) {
            observer.update();
        }
    }

    triggerChange() {
        console.log('The subject has changed.');
        this.notifyObservers();
    }
}

/* 观察者类 */
class Observer {
    constructor(name) {
        this.name = name;
    }

    update() {
        console.log(`${this.name} has been notified.`);
    }
}

const subject = new Subject();
const observer1 = new Observer('Observer1');
const observer2 = new Observer('Observer2');

// 添加观察者
subject.addObserver(observer1);
subject.addObserver(observer2);

// 触发变化
subject.triggerChange();

五、JS观察者模式once

为了避免重复调用观察者的update()方法,我们可以在Observer类中加入once属性,标识观察者只需要被通知一次。

/* 目标对象类 */
class Subject {
    constructor() {
        this.observers = [];
    }

    addObserver(observer) {
        this.observers.push(observer);
    }

    removeObserver(observer) {
        const index = this.observers.indexOf(observer);
        if (index >= 0) {
            this.observers.splice(index, 1);
        }
    }

    notifyObservers() {
        for (let observer of this.observers) {
            observer.update();
            if (observer.once) {
                this.removeObserver(observer);
            }
        }
    }

    triggerChange() {
        console.log('The subject has changed.');
        this.notifyObservers();
    }
}

/* 观察者类 */
class Observer {
    constructor(name, once = false) {
        this.name = name;
        this.once = once;
    }

    update() {
        console.log(`${this.name} has been notified.`);
    }
}

const subject = new Subject();
const observer1 = new Observer('Observer1', true);
const observer2 = new Observer('Observer2');

// 添加观察者
subject.addObserver(observer1);
subject.addObserver(observer2);

// 触发变化
subject.triggerChange();

// 再次触发变化
subject.triggerChange();

六、JS观察者模式的项目

JS观察者模式在实际项目中较为常见,特别是在前端开发中,有许多场景可以用它来实现交互效果。

以购物车为例,当用户点击添加购物车按钮时,购物车图标需要相应变化,并且在购物车中需要显示添加的商品信息,这时候我们可以借助观察者模式来实现自动刷新购物车。

<!-- HTML部分 -->
<button id="add-button">添加购物车</button>
<div id="cart-icon">购物车图标</div>
<div id="cart-content">购物车内容</div>

<!-- JS部分 -->
/* 目标对象类 */
class Subject {
    constructor() {
        this.observers = [];
    }

    addObserver(observer) {
        this.observers.push(observer);
    }

    removeObserver(observer) {
        const index = this.observers.indexOf(observer);
        if (index >= 0) {
            this.observers.splice(index, 1);
        }
    }

    notifyObservers() {
        for (let observer of this.observers) {
            observer.update();
        }
    }

    triggerChange() {
        console.log('The subject has changed.');
        this.notifyObservers();
    }
}

/* 观察者类 */
class Observer {
    constructor(name, data) {
        this.name = name;
        this.data = data;
    }

    update() {
        console.log(`${this.name} has been notified.`);
        this.render();
    }

    /* 渲染购物车 */
    render() {
        let cartString = '';
        for (let item of this.data) {
            cartString += `

${item.name} 数量:${item.quantity}

`; } document.getElementById('cart-content').innerHTML = cartString; } } const subject = new Subject(); // 添加购物车按钮事件 document.getElementById('add-button').addEventListener('click', () => { /* 添加商品到购物车 */ // do something... const data = [ {name: '商品1', quantity: 2}, {name: '商品2', quantity: 1} ]; /* 通知购物车图标和内容刷新 */ subject.triggerChange(); }); // 设置购物车图标 const observer1 = new Observer('CartIcon', [ {name: '商品1', quantity: 2}, {name: '商品2', quantity: 1} ]); // 添加购物车内容 const observer2 = new Observer('CartContent', [ {name: '商品1', quantity: 2}, {name: '商品2', quantity: 1} ]); // 添加观察者 subject.addObserver(observer1); subject.addObserver(observer2);

七、JS观察者模式源码

JS观察者模式在前端中很常见,并且已经被各大框架所接受和使用,例如Angular、React、Vue等。以下是Vue.js的源码中Observer类的定义。

/* Vue.js Observer类 */
class Observer {
    constructor(value) {
        this.value = value;
        this.dep = new Dep();

        // 对象属性监听
        def(value, '__ob__', this);

        if (Array.isArray(value)) {
            // 数组监听
            if (hasProto) {
                protoAugment(value, arrayMethods);
            } else {
                copyAugment(value, arrayMethods, arrayKeys);
            }
            this.observeArray(value);
        } else {
            this.walk(value);
        }
    }

    /* 遍历对象属性 */
    walk(obj) {
        const keys = Object.keys(obj);
        for (let i = 0; i < keys.length; i++) {
            defineReactive(obj, keys[i]);
            
JS观察者模式

2023-05-17
java观察者模式,我的世界java观察者模式

2023-01-09
java观察者模式,java观察者模式与消息队列

2023-01-07
观察者模式java,观察者模式java代码

2022-11-27
java观察者,java观察者模式监控线程

2022-11-30
C#观察者模式详解

2023-05-20
Java观察者模式详解

2023-05-22
Java观察者模式的应用与解析

2023-05-19
Android观察者模式的详解

2023-05-21
观察者模式Java详解

2023-05-18
深入浅出:观察者设计模式

2023-05-22
JavaObservable:使用观察者模式实现事件监听

2023-05-22
如何为Android建立可观察的模式

在Android应用开发中,使用可观察的模式(Observable Pattern)可以帮助我们更好地管理应用程序中的数据,并且在视图更新时也非常有用。在本文中,我们将讨论如何为Android应用程序

2023-12-08
Android中使用观察者模式实现数据更新实时通知

一、什么是观察者模式? 观察者模式(Observer Pattern)是一种设计模式,用于当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。该模式也称作发布-订阅模式(Publis

2023-12-08
java方法整理笔记(java总结)

2022-11-08
重学java笔记,java笔记总结

2022-11-23
印象笔记记录java学习(Java成长笔记)

2022-11-12
发布订阅者模式

2023-05-20
htmljs编程笔记(html代码笔记)

本文目录一览: 1、html代码和JS代码有什么区别 2、如何在html中调用js函数 3、JavaScript学习笔记之数组基本操作示例 4、HTML5初学者笔记 5、《web前端笔记7》js字符—

2023-12-08
数据库的笔记mysql,数据库管理系统笔记

2022-11-24