怎样用JavaScript实现观察者模式

概述

观察者模式又被称为发布-订阅模式,是设计模式中的一种行为型模式;

定义:

观察者模式定义了一种一对多的对象依赖关系,当被依赖的对象的状态发生了改变,所有依赖它的对象都会得到通知;

白话解释:

假如你去苹果专卖店买最新款的iphone11,因为iphone11刚出来不久,正处旺季,供货不足;当你去专卖店的时候,店员告诉你暂时没货了,但是你可以留下你的联系方式,如果货到了,会第一时间通知;当然你肯定不会每天都去专卖店问iphone11到货没有,也不会天天给专卖店打电话,因为你有你自己的工作和生活,不可能有那么多闲暇时间;所以此时,店员让你留下联系方式,到货了第一时间通知你,不会给你带来麻烦,而你只需要等着专卖店的电话即可;而这种方法就是一种典型的观察者模式;

首先我们还是来分析一下:

1.订阅方法:我们把联系方式给专卖店店员是属于一种消息订阅的消息,因为只有这样你才能及时的知道iphone11到货了,所有我们需要一个订阅行为的具体方法;

2.预订列表:要知道iphone11是属于新版iphone,所以肯定不会是只有你一个人去预订,所以店员为了方便统计还需要一个预订列表来统计所有的预订者的联系方式以及预订手机版本信息,所以我们这里先给它定义为一个对象;key代表是预订者的联系方式,value代表预订手机版本信息;

3.发布方法:当iphone11到货的时候,专卖店肯定要根据预订列表来进行统一发布消息("iphone11到货了,大家快来抢!!!"),所以专卖店需要一个发布方法来实行具体的发布行为;、

4.取消订阅:万物相对,能订阅肯定就能取消订阅;在等待iphone11到货通知的时候,你急着用手机,所以直接买了华为的某款,所以iphone11暂时对你来说需求不大,因为你已经有了手机所以专卖店的iphone11是否到货对你来说没有任何意义了;所以此时你不想被打扰,需要取消订阅消息;所以我们需要一个取消订阅方法来实现具体的取消订阅的行为;

观察者模式的应用场景

1、DOM事件

如果你是一个前端开发人员,不管你读这篇文章之前是否已经了解观察者模式,但是我能肯定你已经用过观察者模式;

document.body.addEventListener('click', function() {
    console.log('hello world!');
});

这段代码看着眼熟吗?是的,这是一个DOM事件的监听;我们通过给body订阅click事件(click相当于上面的订阅方法),因为浏览器并不知道你什么时候点击鼠标,所以等你触发click事件的时候才会触发函数给你发布通知(发布方法);DOM事件就是一个观察者模式的实现;

2、vue双向绑定v-model

我们作为前端开发人员,肯定知道vue是一个MVVM模式的框架;vue的核心就是双向绑定,那么双向绑定的实现实际上就是一种观察者模式;因为你首先绑定了一个数据之后(订阅方法),浏览器并不知道你什么时候修改,你页面上所有绑定了该数据或者依赖该数据的节点其实就是一个预订列表,只有等你修改了该数据的值的时候,vue才会通知(发布方法)到依赖该数据的方法/数据进行相应的操作或刷新;

当然观察者模式绝不仅限于这俩种实现场景,在我们的生活中、业务场景中有很多观察者模式的示例,之前我们第一篇工厂模式介绍设计模式的时候就说过了,设计模式是一种解决问题的思路而非一种固定的公式,那么我们怎么实现观察者模式呢?

观察者模式的实现

//定义商家
var merchants = {};
//定义预订列表
merchants.orderList = {};
//将增加的预定者添加到预订列表中   (订阅方法)
merchants.listen = function(id,info){
    //如果存在
    if(!this.orderList[id]){
        // (预订列表)
        this.orderList[id] = [];
    }
    // 将用户的预定的产品信息存入到数组中
    this.orderList[id].push(info);
}
//发布信息(发布方法)
merchants.publish = function(){
    var id = Array.prototype.shift.call(arguments);
    var infos = this.orderList[id];
    if(!infos || infos.length === 0){
        console.log("您还没有预定信息");
        return false;
    }

    for(var i = 0;i < infos.length;i++){
        console.log("预定成功");
        console.log("尊敬的用户:")
        infos[i].apply(this,arguments);
        console.log("到货了");
    }
}
//取消订阅
merchants.remove = function(id,fn){
    var infos = this.orderList[id];
    if(!infos){ return false}

    if(!fn){
        console.log(123);
    }else{
        for(var i = 0;i < infos.length;i++){
            if(infos[i] === fn){
                infos.splice(i,1);
            }
        }
    }
}
let customeA = function(){
    console.log("黑色尊享版一台");
}

merchants.listen("15172103336",customeA);
merchants.remove("15172103336",customeA);
merchants.publish("15172103336");

上面的代码稍微有点长,不过没有很难;首先我们是定义了一个对象是作为商家,然后定义了一个空的对象作为预订列表,再一步步的实现我们的订阅方法和发布以及取消订阅的方法;逻辑不复杂,但是有一些语法需要讲解一下:

发布方法中的var id = Array.prototype.shift.call(arguments);这句的意思是将merchants.publish("15172103336");方法调用的时候第一个参数返回给它然后复制为id,所以其实此时的id值为”15172103336“;

infos[i].apply(this,arguments);这个方法也不是特别好理解,首先infos里装的是预订者的手机号码以及手机版本信息,所以我们infos[i].apply(this,arguments);这个方法其实就是将"15172103336"对应的手机版本信息函数进行调用了一遍;实际上等于infos[i](arguments);

总结

观察者模式不管是在前端领域还是在现实生活中的应用都是有很常见的场景,学好观察者模式有利用我们学习vue的源码知识,当然不仅限于此,所以观察者模式值得我们好好学习,一句话:"你品,你细品!" 今天付出的努力,在日后总会换成工资来回报你的!

以上就是怎样用JavaScript实现观察者模式的详细内容,更多关于JavaScript观察者模式的资料请关注我们其它相关文章!

(0)

相关推荐

  • 怎样用JavaScript实现原型模式

    概述 原型模式是指原型实例指向创建对象的种类,并通过拷贝这些原型创建新的对象,是一种用来创建对象的模式,也就是创建一个对象作为另一个对象的prototype属性: prototype警告:学习了解原型模式前需先学习原型.原型链.prototype.__proto__.constructor等知识: 实现原型模式 ES5中的API:Object.create(prototype, optionalDescriptorObjects) Object.create()方法接收两个参数:第一个参数是__

  • JS命令模式例子之菜单程序

    命令模式的应用场景: 有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么,此时希望用一种松耦合的方式来设计软件,使得请求发送者和请求接收者能够消除彼此之间的耦合关系. html代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>js:命令模式</title> <script type="

  • JavaScript设计模式之命令模式实例分析

    本文实例讲述了JavaScript设计模式之命令模式.分享给大家供大家参考,具体如下: 第一,命令模式: (1)用于消除调用者和接收者之间直接的耦合的模式,并且可以对(调用这个过程进行留痕操作) (2)真的不要乱用这个模式,以为他使你简单调用写法变得非常的复杂和有些难以理解. (3)你的业务出现了 (回退操作)(重做操作)的需求的时候你就要考虑使用这个模式了. 命令的原理: 一种情况为发出者直接作用于执行者,这样耦合度很高,另外一种情况为,在发出者和执行者之间增加一个用存储命令的命令访问库也即命

  • 深入理解JavaScript系列(34):设计模式之命令模式详解

    介绍 命令模式(Command)的定义是:用于将一个请求封装成一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及执行可撤销的操作.也就是说改模式旨在将函数的调用.请求和操作封装成一个单一的对象,然后对这个对象进行一系列的处理.此外,可以通过调用实现具体函数的对象来解耦命令对象与接收对象. 正文 我们来通过车辆购买程序来展示这个模式,首先定义车辆购买的具体操作类: 复制代码 代码如下: $(function () { var CarManager = { // 请求

  • JavaScript设计模式之命令模式

    命令模式是JavaScript设计模式中行为型的一种设计模式: 定义:向某些对象发送请求,但是并不知道被请求的操作具体是什么,所以我们希望以一种松耦合的方式来设计程序,使得请求发送者和接收者之间能够消除彼此之间的耦合关系:而我们的这种松耦合的方式就是命令模式: 白话解释:假如你是你们公司研发部门团队leader,这时你们领导分布给你一个任务,你粗略的看了一下,很简单的需求比较容易实现:而你作为团队leader,每天肯定会有很多事情,所以你准备把需求直接丢给组员去开发和实现:领导根本不在意是你做的

  • JS设计模式之命令模式概念与用法分析

    本文实例讲述了JS设计模式之命令模式概念与用法.分享给大家供大家参考,具体如下: 客户创建命令:调用者执行该命令:接收者在命令执行时执行相应操作 简单命令对象一般用来消除二个对象(调用者和接收者)之间的耦合,而复杂的命令对象则一般用来封装不可分的或事务性的指令. 命令模式的主要用途是把调用对象(用户界面.API和代理等)与实现操作的对象隔离开.凡是两个对象间互动方式需要有更高的模块化程度时都可以用到这种模式. 命令的意思是用一个简单方法或函数去执行和这个命令相关的实际操作.就如同用遥控器打开电视

  • JavaScript设计模式经典之命令模式

    一.命令模式概念 命令模式(Command)的定义是:用来对方法调用进行参数化处理和传送,经过这样处理过的方法调用可以在任何需要的时候执行.也就是说该模式旨在将函数的调用.请求和操作封装成一个单一的对象,然后对这个对象进行一些列的处理.他也可以用来消除调用操作的对象和实现操作的对象之间的耦合.这为各种具体的类的更换带来了极大的灵活性. 二.命令模式的作用和注意事项 模式作用: 1.将函数的封装.请求.调用结合为一体 2.调用具体的函数解耦命令对象与接收对象 3.提高程序模块化的灵活性 注意事项:

  • javascript设计模式 – 命令模式原理与用法实例分析

    本文实例讲述了javascript设计模式 – 命令模式原理与用法.分享给大家供大家参考,具体如下: 介绍:命令模式是一种数据驱动的设计模式,将请求以命令的形式包裹在对象中,并传递给调用对象.命令模式的核心在于引入了命令类,通过命令类来降低发送者和接受者的耦合度. 定义:将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作.命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务(Transaction)模式. 场景:我们通过

  • JavaScript命令模式原理与用法实例详解

    本文实例讲述了JavaScript命令模式原理与用法.分享给大家供大家参考,具体如下: 第一,命令模式: (1)用于消除调用者和接收者之间直接的耦合的模式,并且可以对(调用这个过程进行留痕操作) (2)真的不要乱用这个模式,以为他使你简单调用写法变得非常的复杂和有些难以理解. (3)你的业务出现了 (回退操作)(重做操作)的需求的时候你就要考虑使用这个模式了. 命令的原理: 一种情况为发出者直接作用于执行者,这样耦合度很高,另外一种情况为,在发出者和执行者之间增加一个用存储命令的命令访问库也即命

  • 详解Javascript实践中的命令模式

    定义 Encapsulate a request as an object, thereby letting you parameterize other objects with different requests, queue or log requests,and support undoable operations." 「命令模式」将「请求」封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象,同时支持可撤消的操作. 这里的「请求」的定义,并不是我们前端常说的「Ajax 请求

随机推荐