介绍

观察者模式又叫发布订阅模式(Publish/Subscribe),一个目标对象管理所有相依于它的观察者对象。该模式中存在两个角色:观察者和被观察者。目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。

该模式通常有两种实现策略:"推"(push) 和 "拉"(pull)

例:对于报社可能雇佣投送人员四处送报给订阅者,这就是主动推送。而对于规模小的报社没有足够的资源去雇佣投送员,这时候可以采取 "拉" 的方式。就是在订阅者附近提供自己的数据,供订阅者 "拉" 自己所需的数据。

实现

push

  1. var Observable = {
  2. observers: []
  3. , lastId: -1
  4. , addObserver: function(observer) {
  5. this.observers.push({
  6. callback: observer
  7. , id: ++this.lastId
  8. })
  9. return this.lastId
  10. }
  11. , removeObserver: function(id) {
  12. for (var i = this.observers.length - 1; i >= 0; i--) {
  13. this.observers[i]
  14. if (this.observers[i].id == id) {
  15. this.observers.splice(i, 1)
  16. return true
  17. }
  18. }
  19. return false
  20. }
  21. , notifyObservers: function(message) {
  22. for (var i = this.observers.length - 1; i >= 0; i--) {
  23. this.observers[i].callback(message)
  24. };
  25. }
  26. }
  27. var id_1 = Observable.addObserver(function(message){
  28. console.log("First observer message:" + message)
  29. })
  30. var observer = function(message){
  31. console.log("Second observer message:" + message)
  32. }
  33. var id_2 = Observable.addObserver(observer)
  34. Observable.notifyObservers('test 1')
  35. Observable.removeObserver(id_2)
  36. Observable.notifyObservers('test 2')

pull

  1. var Observable = {}
  2. ;(function(O){
  3. var observers = []
  4. , privateVar
  5. O.addObserver = function(observer) {
  6. observers.push(observer)
  7. }
  8. O.removeObserver = function(observer) {
  9. var index = observers.indexOf(observer)
  10. if (~index) {
  11. observers.splice(index, 1)
  12. }
  13. }
  14. O.notifyObservers = function() {
  15. for (var i = observers.length - 1; i >= 0; i--) {
  16. observers[i].update()
  17. };
  18. }
  19. O.updatePrivate = function(newValue) {
  20. privateVar = newValue
  21. this.notifyObservers()
  22. }
  23. O.getPrivate = function() {
  24. return privateVar
  25. }
  26. }(Observable))
  27. Observable.addObserver({
  28. update: function(){
  29. this.process()
  30. }
  31. , process: function(){
  32. var value = Observable.getPrivate()
  33. console.log("Private value is: " + value)
  34. }
  35. })
  36. Observable.updatePrivate('test 1')
  37. // Private value is: test 1
  38. Observable.updatePrivate('test 2')
  39. // Private value is: test 2

被观察对象将通知所有的观察者,并且每个观察者将从被观察对象中提取所需的信息。

让多个对象都具有观察者发布订阅的功能

  1. var observer = {
  2. addSubscriber:function (callback) {
  3. this.subscribers[this.subscribers.length] = callback;
  4. },
  5. removeSubscriber:function (callback) {
  6. for (var i = 0; i < this.subscribers.length; i++) {
  7. if (this.subscribers[i] === callback) {
  8. delete(this.subscribers[i]);
  9. }
  10. }
  11. },
  12. publish:function (what) {
  13. for (var i = 0; i < this.subscribers.length; i++) {
  14. if (typeof this.subscribers[i] === 'function') {
  15. this.subscribers[i](what);
  16. }
  17. }
  18. },
  19. make:function (o) { // turns an object into a publisher
  20. for (var i in this) {
  21. o[i] = this[i];
  22. o.subscribers = [];
  23. }
  24. }
  25. };
  26. var blogger = {
  27. writeBlogPost:function () {
  28. var content = 'Today is ' + new Date();
  29. this.publish(content);
  30. }
  31. };
  32. var la_times = {
  33. newIssue:function () {
  34. var paper = 'Martians have landed on Earth!';
  35. this.publish(paper);
  36. }
  37. };
  38. observer.make(blogger);
  39. observer.make(la_times);
  40. var jack = {
  41. read:function (what) {
  42. console.log('I just read that ' + what)
  43. }
  44. };
  45. var jill = {
  46. gossip:function (what) {
  47. console.log('You didn\'t hear it from me, but ' + what)
  48. }
  49. };
  50. blogger.addSubscriber(jack.read);
  51. blogger.addSubscriber(jill.gossip);
  52. blogger.writeBlogPost();
  53. blogger.removeSubscriber(jill.gossip);
  54. blogger.writeBlogPost();
  55. la_times.addSubscriber(jill.gossip);
  56. la_times.newIssue();

避免创建多个被观察者对象,可以增加 "命名空间"

  1. var Observable = {
  2. observers: []
  3. , addObserver: function(topic, observer) {
  4. this.observers[topic] || (this.observers[topic] = [])
  5. this.observers[topic].push(observer)
  6. }
  7. , removeObserver: function(topic, observer) {
  8. if (!this.observers[topic])
  9. return;
  10. var index = this.observers[topic].indexOf(observer)
  11. if (~index) {
  12. this.observers[topic].splice(index, 1)
  13. }
  14. }
  15. , notifyObservers: function(topic, message) {
  16. if (!this.observers[topic])
  17. return;
  18. for (var i = this.observers[topic].length - 1; i >= 0; i--) {
  19. this.observers[topic][i](message)
  20. };
  21. }
  22. }
  23. Observable.addObserver('cart', function(message){
  24. console.log("First observer message:" + message)
  25. })
  26. Observable.addObserver('notificatons', function(message){
  27. console.log("Second observer message:" + message)
  28. })
  29. Observable.notifyObservers('cart', 'test 1')
  30. // First observer message:test 1
  31. Observable.notifyObservers('notificatons', 'test 2')
  32. // Second observer message:test 2

相关阅读

javascript-observer-publish-subscribe-pattern

深入理解JavaScript系列(32):设计模式之观察者模式

javascript-patterns-observer

javaScript 设计模式系列之一:观察者模式的更多相关文章

  1. javascript设计模式系列

    javascript设计模式系列   创建型: 1.抽象工厂模式(Abstract Factory) 2.构建者模式(Builder) 3.工厂方法模式(Factory Method) 4.原型模式( ...

  2. 【JavaScript设计模式系列---开篇预览】

    转:http://www.cnblogs.com/Darren_code/archive/2011/08/31/JavascripDesignPatterns.html 2011-08-31 23:5 ...

  3. Javascript设计模式系列三

    继承,一个类或对象继承另一个类或对象的三种方法.类式继承.原型式继承.掺元类. 一.类式继承,原型链.Extend函数. <script type="text/javascript&q ...

  4. Javascript设计模式系列二

    创建对象的基本模式,一.门户大开型,二.采用下划线来表示属性和方法的私用性,三.使用闭包来创建私用的成员. 一.门户大开型.只能提供公用成员.所有属性和方法都公开的.可访问的.这些共用属性都要使用th ...

  5. Javascript设计模式系列一

    定义类,方法赋值给prototype属性各种写法: 方法一: <script type="text/javascript"> ////定义Message类 var Me ...

  6. 【读书笔记】读《JavaScript设计模式》之观察者模式

    一.定义 在事件驱动的环境中,比如浏览器这种持续寻求用户关注的环境中,观察者模式(又名发布者-订阅者(publisher-subscripber)模式)是一种管理人与其任务之间的关系(确切地讲,是对象 ...

  7. 设计模式系列之观察者模式(Observer Pattern)

    意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 主要解决:一个对象状态改变给其他对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作 ...

  8. [转] 浅析JavaScript设计模式——发布-订阅/观察者模式

    前一段时间一直在写CSS3的文章 一直都没写设计模式 今天来写写大名鼎鼎观察者模式 先画张图 观察者模式的理解 我觉得还是发布-订阅模式的叫法更容易我们理解 (不过也有的书上认为它们是两种模式……)  ...

  9. C#设计模式系列:观察者模式(Observer)

    在软件构建过程中,需要为某些对象建立一种“通知依赖关系”,即一个对象的状态发生改变,所有的依赖对象都需要得到通知. 1.观察者模式简介 1.1>.定义 定义对象间的一种一对多的依赖关系,当一个对 ...

随机推荐

  1. socket bind详解

    http://www.cnblogs.com/nightwatcher/archive/2011/07/03/2096717.html 在最开始接触bind的时候,只是在写基于tcp的server端的 ...

  2. JQ实战一之烟花

    本次的效果大概为当用户点击网页时,网页下方弹出一个类似烟花的长条条,然后在桌面上散开以达成类似烟花的特效.话不多说先上图. 首先布局,布局很简单 <style> body { backgr ...

  3. 看Lucene源码必须知道的基本规则和算法

    上中学的时候写作文,最喜欢的季节我都是写冬天.虽然是因为写冬天的人比较少,那时确实也是对其他季节没有什么特殊的偏好,反而一到冬天,自己皮肤会变得特别白.但是冬天啊,看到的只有四季常青盆栽:瓜栗(就是发 ...

  4. JavaScript高级内容:原型链、继承、执行上下文、作用域链、闭包

    了解这些问题,我先一步步来看,先从基础说起,然后引出这些概念. 本文只用实例验证结果,并做简要说明,给大家增加些印象,因为单独一项拿出来都需要大篇幅讲解. 1.值类型 & 引用类型 funct ...

  5. NPOI操作类

    using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Secu ...

  6. 学习vue 20天,我写了点东西

    往昔 最初团队里使用Angularjs进行开发,刚开始还好,到了项目后期越发感觉Angularjs太重了,以至于后来重构项目时,毅然放弃Angularjs,投入了Vue的怀抱.除了组建团队时,是我搭建 ...

  7. 【Windows 10 应用开发】输入模拟

    ---恢复内容开始--- Input Injection 直译为:输入注入.通俗的译法为:模拟输入.此注入行为可以模拟以下几种输入行为: 1.键盘按键. 2.鼠标. 3.触控. 4.书写笔输入. 5. ...

  8. Docker for Mac与IntelliJ Docker Integration插件的兼容性问题

    笔者在自己的Mac上安装的是Docker for Mac,而不是Docker Toolbox. 这两者最主要的区别在于Docker for Mac用HyperKit作为虚拟化解决方案而不是Virtua ...

  9. js日期转化(计算一周的日期)

    之前做项目的时候遇到过一个日期转化的问题,一个日期控件和近一天,近七天和近一月的的联动效果.发现自己不会,后来就百度了一下解决了这个问题. 现在抽空又写了一个时间转化的案例(计算一周的日期),因为之前 ...

  10. 工资不高也要给自己放假 这几款APP估计你用得上

    我是这样的一个人,我宁愿工资不高,只要给我足够的假期,那我就满足了.都说上班就是为了赚钱,但如果身体不好,赚再多的钱也是无福享受,所以建议各位,有机会的话,一定要抽出时间去旅游,去放松. 现在我们外出 ...