Welcome 微信登录

首页 / 脚本样式 / JavaScript / 学习JavaScript设计模式之观察者模式

一、定义
观察者模式(发布-订阅模式):其定义对象间一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
在JavaScript中,一般使用事件模型来替代传统的观察者模式。
好处:

  • (1)可广泛应用于异步编程中,是一种替代传递回调函数的方案。
  • (2)可取代对象之间硬编码的通知机制,一个对象不用再显示地调用另外一个对象的某个接口。两对象轻松解耦。
二、DOM事件–观察者模式典例
需要监控用户点击document.body的动作,但是我们没有办法预知用户将在什么时间点击。
所以,我们订阅document.body上的click事件,当body节点被点击时,body节点便向订阅者发布这个消息!
document.body.addEventListener("click", function() {console.log(1);}, false);// 可以多个订阅者document.body.addEventListener("click", function() {console.log(2);}, false);doucment.body.click();
某网站有header头部、nav导航、消息列表等模块。这几个模块的渲染都需要获取用户登陆信息。
(1)一般写法:
$.ajax({url: "./login",type: "post",contentType: "application/json",dataType:"json",success: function(data) {if(data.status === "success") {// 登录成功,渲染header、navheader.setInfo(data.headerInfo);nav.setInfo(data.navInfo);}}});
(2)使用观察者模式,很轻松解耦!

$.ajax({...,success: function(data) {if(data.status === "success") {// 登录成功,发布登陆成功消息login.trigger("loginsuccess", data);}}});var header = (function() {// 监听消息login.listen("loginsuccess", function(data){header.setInfo(data.headerInfo);});return {setInfo: function(data) {console.log("设置header信息");}};})();var nav = (function() {login.listen("loginsuccess", function(data){nav.setInfo(data.navInfo);});return {setInfo: function(data) {console.log("设置nav信息");}}})();
三、通用观察者模式

/* * 示例: * Event.create("namespace1").listen("click", function(a){ * console.log(a); * }); * Event.create("namespace1").trigger("click", 1); */var Event = (function() {var global = this,Event,_default = "default";Event = function() {var _listen,_trigger,_remove,_slice = Array.prototype.slice,_shift = Array.prototype.shift,_unshift = Array.prototype.unshift,namespaceCache = [],_create,find,each = function( ary, fn) {var ret;for(var i = 0, l = ary.length; i < l; i++) {var n = ary[i];ret = fn.call(n, i, n);}return ret;};// 订阅_listen = function(key, fn, cache) {if(!cache[key]) {cache[key] = [];}cache[key].push(fn);};// 移除订阅_remove = function(key, cache, fn) {if(cache[key]) {if(fn) {for(var i = cache[key].length; i >=0; i++) {if(cache[key][i] === fn) {cache[key].splice(i, 1);}}}else {cache[key] = [];}}};// 发布_trigger = function() { var cache = _shift.call(arguments), key = _shift.call(arguments), args = arguments, _self = this, ret, stack = cache[key];if(!stack || !stack.length) {return;}return each(stack, function() {return this.apply(_self, args);});};// 创建命名空间_create = function(namespace) {var namespace = namespace || _default;var cache = {},offlineStack = [], // 离线事件ret = {listen: function (key, fn, last) {_listen(key, fn, cache);if (offlineStack == null) {return;}if (last === "last") {offlineStack.length && offlineStack.pop()();} else {each(offlineStack, function () {this();});}offlineStack = null;},one: function (key, fn, last) {_remove(key, cache);this.listen(key, fn, last);},remove: function(key, fn, last) {_remove(key, cache, fn);},trigger: function() {var fn,args,_self = this;_unshift.call(arguments, cache);args = arguments;fn = function() {return _trigger.apply(_self, args);};if(offlineStack) {return offlineStack.push(fn);}return fn;}};return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret) : ret;};return {create: _create,one: function(key, fn, last) {var event = this.create();event.one(key, fn, last);},remove: function(key, fn) {var event = this.create();event.remove(key, fn);},listen: function(key, fn, last) {var event = this.create();event.listen(key, fn, last);},trigger: function() {var event = this.create();event.trigger.apply(this, arguments);}};}();return Event;})();
希望本文所述对大家学习javascript程序设计有所帮助。