Javascript设计模式理论与实战:观察者模式

简介:

观察者模式主要应用于对象之间一对多的依赖关系,当一个对象发生改变时,多个对该对象有依赖的其他对象也会跟着做出相应改变,这就非常适合用观察者模式来实现。使用观察者模式可以根据需要增加或删除对象,解决一对多对象间的耦合关系,使程序更易于扩展和维护。

基础知识

观察者模式定义了对象间的一种一对多依赖关系,每当一个对象发生改变时,其相关依赖对象皆得到通知并被进行相应的改变。观察者模式又叫做发布-订阅 模式。生活中有很多类似的关系,比如微信公众号订阅,多个读者订阅一个微信公众号,一旦公众号有更新,多个读者都会收到更新,而这种情况在应用程序中也非 常常见,js绑定各种事件本质上就是观察者模式的实现。
观察者模式是一个非常有用的设计模式,它主要有两个角色组成:
(1)目标对象:作为一对多关系中的一,可以用来管理观察者的增加和删除
(2)观察者对象:观察目标对象,一旦目标发生改变则做出相应的反应

观察者模式的实现

基本示例

在Web开发中,我们经常遇到这种情况,ajax请求数据后,要同时更新数据到页面的不同部分中,这种情况我们可以最直接的在ajax的回调中更新 页面,但是如果要更新的位置很多,我们就要去修改回调函数,这样代码的维护性和扩张性不高,这种情况下,我们就可以用观察者模式来实现。
首先,需要一个最基本的目标对象,我们定义如下:

 
  1. function Subject() { 
  2.     this.observers = []; 
  3. Subject.prototype = { 
  4.     constructor: Subject, 
  5.     subscribe: function (fn) { 
  6.         this.observers.push(fn); 
  7.         return this
  8.     }, 
  9.     unsubscribe: function (fn) { 
  10.         this.observers = this.observers.filter(function (item) { 
  11.             if (item !== fn) { 
  12.                 return item; 
  13.             } 
  14.         }); 
  15.         return this
  16.     }, 
  17.     fire: function (data, context) { 
  18.         this.observers.forEach(function (item) { 
  19.             item.call(context, data); 
  20.         }); 
  21.         return this
  22.     } 
  23. }; 

目标对象Subject中有一个数组,这个数组保存观察者列表,而目标对象提供三个方法:观察对象,取消观察对象,触发对象更新。
我们通过subscribe方法增加观察者,保存到observers数组中,如果有需要可以通过unsubscribe方法取消订阅,然后更新数据时调用fire方法触发,从而通知各个观察者进行相应处理。
假设我们页面有一个主视图和一个侧视图,两个视图都要进行相应的修改,我们可以定义两个对象如下:

 
 
  1. function SideView() { } 
  2. SideView.prototype.render = function (data) { 
  3.     console.log("Side data:" + data); 
  4. function MainView() { } 
  5. MainView.prototype.render = function (data) { 
  6.     console.log("MainView data:" + data); 

上面代码定义了两个对象,分别为侧视图和主视图,两个对象都有相应的渲染页面的方法render,然后我们将两个方法添加到观察者列表中。

 
 
  1. var subject = new Subject(); 
  2. var sideView = new SideView(); 
  3. var mainView = new MainView(); 
  4.  
  5. subject.subscribe(sideView.render) 
  6. subject.subscribe(mainView.render); 
  7. subject.fire("test"); 

通过调用fire方法,传入“test”,从而触发两个render函数。从这段代码中,我们可以很轻松地通过subscribe来添加观察者对象,而不必每次都去修改fire方法。

jQuery中的观察者模式

jQuery中实现观察者模式非常方便,简短的几句代码就可以实现

 
  1. (function ($) { 
  2.             var obj = $({}); 
  3.             $.subscribe = function () { 
  4.                 obj.on.apply(obj, arguments); 
  5.             } 
  6.             $.unsubscribe = function () { 
  7.                 obj.off.apply(obj, arguments); 
  8.             } 
  9.             $.fire = function () { 
  10.                 obj.trigger.apply(obj, arguments); 
  11.             } 
  12.         })(jQuery); 

在jQuery中,通过on方法来绑定事件,off来移除事件,trigger来触发事件,本质上就是一种观察者模式。上面代码中,我们通过一个obj对象来保存观察者对象,我们只要像平时绑定事件一样使用就可以,如下:

 
 
  1. $.subscribe("render", function () { 
  2.     console.log("test"); 
  3. }) 
  4. $.subscribe("render", function () { 
  5.     console.log("test2"); 
  6. }) 
  7. $.fire("render"); 

这段代码分别输出test和test2.我们绑定了两个处理函数到render上,然后通过fire触发render事件,这就实现了观察者模式一对多依赖的特点。

总结

观察者模式是一种很常用的设计模式,因为我们的应用程序中涉及到依赖关系的非常多。常见的比如消息通知,向用户发送一个消息需要同时通知到站内信, 邮件,短信等多种消息,这种一对多的情况非常适合使用观察者模式来实现。使用观察者模式的关键是在于理清目标对象和观察者对象,目标对象通过一个数组对观 察者对象进行管理,更新数据的时候再循环调用观察者对象,从而实现观察者模式。


作者:狼狼的蓝胖子

来源:51CTO

相关文章
|
1月前
|
设计模式 存储 缓存
「全网最细 + 实战源码案例」设计模式——享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在减少大量相似对象的内存消耗。通过分离对象的内部状态(可共享、不变)和外部状态(依赖环境、变化),它有效减少了内存使用。适用于存在大量相似对象且需节省内存的场景。模式优点包括节省内存和提高性能,但会增加系统复杂性。实现时需将对象成员变量拆分为内在和外在状态,并通过工厂类管理享元对象。
176 92
|
21天前
|
设计模式 机器学习/深度学习 前端开发
Python 高级编程与实战:深入理解设计模式与软件架构
本文深入探讨了Python中的设计模式与软件架构,涵盖单例、工厂、观察者模式及MVC、微服务架构,并通过实战项目如插件系统和Web应用帮助读者掌握这些技术。文章提供了代码示例,便于理解和实践。最后推荐了进一步学习的资源,助力提升Python编程技能。
|
11天前
|
监控 JavaScript 前端开发
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
MutationObserver 是一个非常强大的 API,提供了一种高效、灵活的方式来监听和响应 DOM 变化。它解决了传统 DOM 事件监听器的诸多局限性,通过异步、批量的方式处理 DOM 变化,大大提高了性能和效率。在实际开发中,合理使用 MutationObserver 可以帮助我们更好地控制 DOM 操作,提高代码的健壮性和可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
MutationObserver详解+案例——深入理解 JavaScript 中的 MutationObserver:原理与实战案例
|
1月前
|
设计模式 存储 算法
「全网最细 + 实战源码案例」设计模式——命令模式
命令模式(Command Pattern)是一种行为型设计模式,将请求封装成独立对象,从而解耦请求方与接收方。其核心结构包括:Command(命令接口)、ConcreteCommand(具体命令)、Receiver(接收者)和Invoker(调用者)。通过这种方式,命令的执行、撤销、排队等操作更易扩展和灵活。 适用场景: 1. 参数化对象以操作。 2. 操作放入队列或远程执行。 3. 实现回滚功能。 4. 解耦调用者与接收者。 优点: - 遵循单一职责和开闭原则。 - 支持命令组合和延迟执行。 - 可实现撤销、恢复功能。 缺点: - 增加复杂性和类数量。
69 14
「全网最细 + 实战源码案例」设计模式——命令模式
|
1月前
|
设计模式 存储 Java
「全网最细 + 实战源码案例」设计模式——责任链模式
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,允许将请求沿着处理者链进行发送。每个处理者可以处理请求或将其传递给下一个处理者,从而实现解耦和灵活性。其结构包括抽象处理者(Handler)、具体处理者(ConcreteHandler)和客户端(Client)。适用于不同方式处理不同种类请求、按顺序执行多个处理者、以及运行时改变处理者及其顺序的场景。典型应用包括日志处理、Java Web过滤器、权限认证等。
64 13
「全网最细 + 实战源码案例」设计模式——责任链模式
|
1月前
|
设计模式 算法 开发者
「全网最细 + 实战源码案例」设计模式——策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,用于定义一系列可替换的算法或行为,并将它们封装成独立的类。通过上下文持有策略对象,在运行时动态切换算法,提高代码的可维护性和扩展性。适用于需要动态切换算法、避免条件语句、经常扩展算法或保持算法独立性的场景。优点包括符合开闭原则、运行时切换算法、解耦上下文与策略实现、减少条件判断;缺点是增加类数量和策略切换成本。示例中通过定义抽象策略接口和具体策略类,结合上下文类实现动态算法选择。
76 8
「全网最细 + 实战源码案例」设计模式——策略模式
|
1月前
|
设计模式 SQL 算法
「全网最细 + 实战源码案例」设计模式——模板方法模式
模板方法模式是一种行为型设计模式,定义了算法的骨架并在父类中实现不变部分,将可变部分延迟到子类实现。通过这种方式,它避免了代码重复,提高了复用性和扩展性。具体步骤由抽象类定义,子类实现特定逻辑。适用于框架设计、工作流和相似算法结构的场景。优点包括代码复用和符合开闭原则,缺点是可能违反里氏替换原则且灵活性较低。
72 7
「全网最细 + 实战源码案例」设计模式——模板方法模式
|
2月前
|
设计模式
「全网最细 + 实战源码案例」设计模式——模式扩展(配置工厂)
该设计通过配置文件和反射机制动态选择具体工厂,减少硬编码依赖,提升系统灵活性和扩展性。配置文件解耦、反射创建对象,新增产品族无需修改客户端代码。示例中,`CoffeeFactory`类加载配置文件并使用反射生成咖啡对象,客户端调用时只需指定名称即可获取对应产品实例。
96 40
|
1月前
|
设计模式 JavaScript 算法
浅谈几种js设计模式
设计模式是软件开发中的宝贵工具,能够提高代码的可维护性和扩展性。通过单例模式、工厂模式、观察者模式和策略模式,我们可以解决不同场景下的实际问题,编写更加优雅和高效的代码。
33 8
|
2月前
|
设计模式 Java 开发者
「全网最细 + 实战源码案例」设计模式——适配器模式
适配器模式(Adapter Pattern)是一种结构型设计模式,通过引入适配器类将一个类的接口转换为客户端期望的另一个接口,使原本因接口不兼容而无法协作的类能够协同工作。适配器模式分为类适配器和对象适配器两种,前者通过多重继承实现,后者通过组合方式实现,更常用。该模式适用于遗留系统改造、接口转换和第三方库集成等场景,能提高代码复用性和灵活性,但也可能增加代码复杂性和性能开销。
82 28

热门文章

最新文章