通常一个优秀的项目,会使用到很多的设计模式,这些设计模式在我们的解决方案中,会起到十分重要的作用,它的存在,能使项目的结构更加简洁清晰易于理解
所以了解常用的设计模式,会让我们在日常开发更加得心应手,也会让团队沟通变得更加顺畅。
在《设计模式:可复用面向对象软件基础》一书中强调:当我们评估一个面向对象系统的质量时,所使用的方法之一就是判断系统的设计者是否强调了对象之间的公共系统关系

简介

那么在当前这个博文中,我介绍的就是 JavaScript 语言Observer设计模式
初次接触 Observer设计模式,是在 Vue双向数据绑定中。其原理就是使用了 Observer-观察者 对数据进行劫持,然后让数据的读写全部处于监管之中。然后再使用发布-订阅模式Publish-发布者通知到Subscribe-订阅者,对数据进行进行相应操作,比如双向数据绑定中的视图更新

所以,Vue的一个数据的写入,要经过这样一个流程

所以,实际上,Vue 数据的双向绑定,使用到了2个设计模式:Obsever模式Publish–Subscribe模式。(有一些人认为,观察者模式和订阅观察)

Observer模式(观察者模式)

就像发明一个新的东西一样,新的发明,必定会有其在现实世界启发
就好比雷达的发明,源自于蝙蝠超声波回声定位火箭的发明,源自于水母、墨鱼反冲运动

无独有偶,观察者模式也一样。在现实社会中,经常会出现观察者这个身份。比如书店,他们就是观察者。既然,有了观察者,那一定会有被观察者,他们就像是出版社
书店“监视”各个出版社的新书,若出版社出现了新书(观察者在监视的行为),则书店获得了出版社的信息(被观察者的对象信息)和出版社的发布新书(被观察者的变化),然后书店将其发布的新书拿到,并告诉关注该类书的读者(观察者做出相应操作)

Observer模式的大致流程如上。话不多说,我们着手开始用 JavaScript 实现Observer模式

设计模式中的对象

Observer 观察者

Observer是一个监视被观察者的对象,它需要提供一个接口,对数据发生改变时,做出的行为进行定义。

Subject 被观察者

在出现观察者关心的事件时,要同时通知多个观察者。

抽象模型的代码实现

Observer 观察者
var Observer = function () {};
// 观察者包含一个notify(通知)的回调方法
Observer.prototype.notify = function (info) {// 在该方法内做出操作console.log(`观察者发现 ${info} 出现更改`);
};
Subject 被观察者
var Subject = function (info) {// 注册自己(被观察者)的信息this.info = info;// 已经注册的观察者的列表this.observerList = [];
};
Subject.prototype = {// 注册一个监视当前对象的观察者到观察者列表register: function (observer) {this.observerList.push(observer);},// 不在关注当前对象的观察者,注销观察者对象remove: function (observer) {// 获得当前观察者列表的长度var listLength = this.observerList.length;for (var i = 0; i < listLength; i++) {if ((observer = this.observerList[i])) {// 从观测者列表删除该观察者this.observerList.splice(i, 1);return true;}}return false;},// 通知所有注册的观察者对象update: function () {var observer;// 获得当前观察者列表的长度var listLength = this.observerList.length;for (var i = 0; i < listLength; i++) {observer = this.observerList[i];// 调用Observer对象的notify回调方法observer.notify(this.info);}},
};
小结

以上便是Observer模式的代码实现雏形,主要的流程逻辑已经包括在其中了。但是在具体实现的时候,可以做出部分的调整。

比如:

observer.notify(this.info);

这一句代码可以不一定要传输对象自身的所有信息,放在出版社那,可能只需要传入一个新发布的书名。

那么接下来,我们按照之前的出版社-书店-读者的例子,进行一个具体实例的代码实现。


具体实例的代码实现

Observer 观察者(书店) 定义
var BookStore = function () {};
// 书店包含一个notify(通知)的回调方法
BookStore.prototype.notify = function (CompanyName,BookName) {// 在该方法内做出操作console.log(`读者快来,我这出了新书:${CompanyName} 发版的 ${BookName}`);
};
Subject 被观察者(出版社) 定义
var Company = function (CompanyName) {// 出版社名称this.Name = CompanyName;// 新的书名this.NewBookName = "";// 已经注册的书店的列表this.bookStoreList = [];
};
Company.prototype = {// 注册一个监视当前对象的书店到书店列表register: function (bookStore) {this.bookStoreList.push(bookStore);},// 不在关注当前对象的书店,注销书店对象remove: function (bookStore) {// 获得当前书店列表的长度var listLength = this.bookStoreList.length;for (var i = 0; i < listLength; i++) {if ((bookStore == this.observerList[i])) {// 从书店列表删除该观察者this.bookStoreList.splice(i, 1);return true;}}return false;},// 通知所有注册的书店对象publish: function (BookName) {// 记录新发布书的名字this.NewBookName = BookName;var bookStore;// 获得当前书店列表的长度var listLength = this.bookStoreList.length;for (var i = 0; i < listLength; i++) {bookStore = this.bookStoreList[i];// 调用BookStore对象的notify回调方法bookStore.notify(this.Name,this.NewBookName);}},
};
具体使用
// 初始化一个出版社——VicoHu出版社
var company = new Company("VicoHu出版社");// 初始化三家商店
var bookStore1 = new BookStore("小胡书店");
var bookStore2 = new BookStore("二刘书店");
var bookStore3 = new BookStore("大黄书店");// 重写bookStore3的notify方法实现发布新书时的不同操作
bookStore3.notify = function (CompanyName, BookName) {// 在该方法内做出操作console.log(`${this.Name}促销,新书上架:${CompanyName} 发版的 ${BookName},比其他的店都要便宜很多。`);
};// 将三家商店注册到出版社的商店列表里
company.register(bookStore1);
company.register(bookStore2);
company.register(bookStore3);// 发布新书
company.publish("《挪威的森林》");// 控制台输出如下内容
/*** 小胡书店有促销活动!!!!! 读者快来,我这出了新书:VicoHu出版社 发版的 《挪威的森林》* 二刘书店有促销活动!!!!! 读者快来,我这出了新书:VicoHu出版社 发版的 《挪威的森林》* 大黄书店促销,新书上架:VicoHu出版社 发版的 《挪威的森林》,比其他的店都要便宜很多。*/
小结

在上面的具体实例的代码实现中,我们完成了书店的创建,和出版社的创建,并且将多个商店注册到出版社,并在出版社发布新书的时候,通知给所有的商店,让商店发出广告和通知给我们(读者)。
其实,从本质上而言,商店(观察者)是被动的,它需要依赖于出版社(被观察者调用notify方法,来完成商店的广告发布。
但是,商店的广告的发布,可以通过重写 notify 方法来进行自定义的操作。


总结

Observer 设计模式优点缺点都比较明显

Observer模式 优点
  1. 解耦。这是现在大多数的设计模式都在做的一件事情,例如:MVC、MVVM等。其好处就在于,不需要在设计观察者的时候,关注被观察者的设计。这样可以只需要关注一个notify方法参数。这样的好处很明显,可以把更多的注意力放在设计某个对象的上面。
  2. 广播通讯。如我们后面发布的 《挪威的森林》一书,只需要调用一出版社的publish方法,就可以对所有已经在出版社注册的商店进行通知。
Observer模式 缺点
  1. 观察者过于被动。观察者在这个设计中,其实更像是个被通知的身份,它没有主动了解被观察者的能力。只能根据观察者给的信息,做出反应和操作。
  2. 抗风险性不高。假如某个注册的商店的方法出现问题,或者一直未执行完,会影响到后面的商店的通知。从而影响整体广播的执行。

最后的总结

这世界上没有绝对通用的设计模式,都是根据任务的需求,选择合适的设计模式。
但是,倘若你连某个合适的设计模式都不知道,就会错过一些事半功倍的机会。
所以,只有不断的去学习,不断走出舒适圈,才能让自己走的更远,并成为一个编码更加高效、稳定的开发者。加油吧!各位!

JavaScript设计模式——Observe模式(观察者模式)相关推荐

  1. JavaScript设计模式系列—模式篇总结(上)

    转载请注明预见才能遇见的博客:http://my.csdn.net/ 原文地址:https://blog.csdn.net/pcaxb/article/details/102517956 JavaSc ...

  2. JavaScript设计模式——工厂模式

    在介绍工厂模式之前,首先我们要理解一下什么是设计模式?什么是设计原则? 设计模式: 通常在我们解决问题的时候,很多时候不是只有一种方式,我们通常有多种方式来解决:但是肯定会有一种通用且高效的解决方案, ...

  3. 设计模式-策略模式,观察者模式,装饰者模式,静态工厂模式,工厂方法模式

    设计模式这个东西,永远不是单单从书本上就能获取到的东西.曾经看到一个比喻,比喻的就很巧妙,文艺复兴时期的教学方式,那时候诞生了很多巨匠,达芬奇,莫开朗基罗,拉斐尔都是在这个时期绽放光芒的巨星.有一种说 ...

  4. 【javascript】javascript设计模式mixin模式

    概述: Mixin是JavaScript中用的最普遍的模式,几乎所有流行类库都会有Mixin的实现.任意一个对象的全部或部分属性拷贝到另一个对象上. 一 .混合对象 二 .混合类 转载于:https: ...

  5. javascript设计模式--命令模式

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>命令模式</title> 5 <meta c ...

  6. javascript设计模式-策略模式(Strategy)

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title></title> 5 <meta chars ...

  7. javascript设计模式-代理模式

    代理的结构 代理模式的最基本形式就是对访问进行控制.代理对象和另一个对象实现的是同样的接口.代理对象只是节制对本体的访问. 代理对象不会在另一个对象上添加或修改方法,也不会简化对象的接口,所有对方法的 ...

  8. JavaScript设计模式——原型模式

    原型模式 用原型实例指向创建对象的类,适用于创建新的对象的类共享原型对象的属性以及方法. JavaScript语言内部实现原型模式,在编程中使用函数的prototype共享方法就是原型模式. func ...

  9. JavaScript设计模式-工厂模式

    作者 | Jeskson 掘金 | https://juejin.im/user/5a16e1f3f265da43128096cb 什么是工厂模式,场景为你去买饺子吃,直接点餐,不用自己做,而餐厅要做 ...

最新文章

  1. AngularJS学习笔记之一: AngularJS入门
  2. android 第三方加密软件,Android实用图文教程之代码混淆、第三方平台加固加密、渠道分发...
  3. asp.net type=file前后台合作 在上传图片到服务器
  4. 一个LINUX高手写给初学者的话
  5. 如何设计实时数据平台(设计篇)
  6. TypeScript 里 object 和 Object 的区别
  7. 滚动条造成页面抖动问题
  8. 常用的Java快捷键有哪些
  9. php什么程度算学会,十天学会PHP - 序1,学会的标准是什么?(20180820-1)
  10. crontab 每天凌晨8点_凌晨3点47分,嘉兴8岁女孩竟独自站在街头,原因竟是…
  11. idea重写接口没有@override_细说 Java Overload 与 Override 差别
  12. 数据工作者必备工作技能:数据治理
  13. 如何准备 Java 初级和高级的技术面试
  14. JAVA分布式(一)——了解分布式
  15. MATLAB角度转换为弧度
  16. Word 2010 从任意页码重新开始
  17. 中国临沂白沙埠第四届洋葱文化节开幕
  18. Discuz仿今日头条模板/Discuz新闻资讯商业版GBK模板
  19. 【18年北京网络赛】Tomb Raider【递归求所有子序列】
  20. 入股不亏!LINQ凭什么被誉为最好的技术?

热门文章

  1. 什么是rpx尺寸单位?
  2. ESP32设备驱动-ISL29125 RGB颜色光传感器驱动
  3. 口语学习大杂烩,收藏了吧,不实用你砍我
  4. ubuntu 22.04 版本如何安装NCL
  5. 厨房必备基本调料及作用
  6. python中保留两位小数的函数_python中round函数保留两位小数的方法
  7. C#常用加密解密工具类(SHA1、MD5、DES、Base64)
  8. 【qt】windows下本地文件的标准url格式
  9. detour TopologyOptimization
  10. css 注入,CSS injection 知识总结