我理解的 js 的观察者模式 Observable
我第一次看 四人帮 写的《设计模式》时一头雾水,现在也是,或许其是针对专业的程序员学习使用的。
通过对Ext / Backbone 源码的学习,可总结如下:
模式 - 就是对解决某一类特定问题的有效总结,并在后续解决同样的问题可以持续使用。
设计模式 - 程序开发者认为自己是优雅的设计师。
观察者模式:主要应用于组件开发,以便组件使用者 可以自行定义某个性方法,在组件达到某种状态时调用。
一、观察者模式原理
组件开发为了保证组件可以在不同的项目中都适用,其必须是对其常用功能 抽象出来 加以实现,绝不会包含具体的业务逻辑
而某一特定的项目使用者在其业务场景中使用组件时不可避免的要加入不同场景的业务逻辑,观察者模式很好的解决了这个的问题。
如下:
- /*
- * 组件开发者A 定义了通用方法 test 供 业务开发者B 使用
- */
- function test(){
- beforeTest && beforeTest()
- // do test something
- console.log( 'test ');
- // do test something
- afterTest && afterTest();
- }
- /*
- * 业务开发者B使用test,不修改test源码的情况下,执行test时,如B需要可以先执行B自定义的方法,test执行结束后还需再执行B自定义的另一方法
- * 双方约定先执行的方法名为 beforeTest
- */
- function beforeTest(){
- console.log('beforeTest')
- /*
- * do beforeTest something
- */
- }
- /*
- * 双方约定后执行的方法名为 afterTest
- */
- function afterTest(){
- console.log('afterTest')
- /*
- * do afterTest something
- */
- }
- /*
- * 示例:
- */
- test(); //控制台会输出 开发者B自定义方法里的值 beforeTest ; afterTest
- //这样每次执行test时,都会执行B自定义的方法
通过上面这种模式,可以降低代码之间的耦合,据实际使用和双方约定,组件使用方可以在组件使用过程中,不对组件进行修改,却可以自由的定义、执行其业务需要的个性化的方法。
上面的方法只是讲了原理,并不适用于实际的项目,且对于beforeTest只能定义一个,经过简单的抽象提取如下
- /*
- * 组件开发者A定义组件 Person 供开发者B使用
- */
- var events = {
- /*
- * 添加 name 对应的 事件callback,保存在this._events里
- */
- on: function( name, callback ){
- this._events || (this._events = {}); //确保this._events存在
- this._events[name] = this._events[name] || [];//确保this._events[name]存在
- this._events[name].push({ callback: callback });//将callback 添加到 this._events[name] 内
- },
- /*
- * 执行已经保存在this._events里的 name 对应的事件
- */
- trigger : function( name ){
- var args = Array.prototype.slice.call( arguments, 1 );
- //将参数中除 name 外的其它参数取出来
- if( this._events && this._events[name] ){ //确保 this._events[name] 存在
- for( var i = 0; i < this._events[name].length; i++){
- //循环执行里面的callback
- this._events[name][i].callback.apply( this, args );
- //将步骤一取出的值作用callback的参数
- }
- }
- },
- /*
- * 删除this._events里 name 对应的事件
- */
- off: function( name ){
- if( this._events ){
- delete this._events[name]; //删除 this._events[name]
- }
- }
- }
- var Person = function( config ){
- this.name = config.name;
- this.age = config.age;
- }
- for( var key in events ){
- Person.prototype[key] = events[key];
- //将events里的属性添加到Person的原型里
- }
- Person.prototype.getName = function(){
- this.trigger('getName', this.name );
- return this.name;
- }
- /*
- * 当设置Person里的名字里,执行一次 setName 监听
- */
- Person.prototype.setName = function( name ){
- this.trigger( 'setName', name );
- this.name = name;
- return this;
- }
- /*
- * 生成一个实例
- */
- var lulu = new Person({ name: 'lulu', age: '25'});
- /*
- * 根据业务的个性化需要 添加一个监听事件,当执行到setName里,执行function,
- */
- lulu.on( 'setName', function( name ){
- console.log('您执行一次setName __ ' + name );
- /*
- * 上面一个无意义的场景
- * 实际的场景可以是setName后会通过 ajax 保存到数据库等操作
- */
- });
- /*
- * 对同一个监听行为可以添加多个 事件
- */
- lulu.on( 'setName', function( name ){
- console.log('您执行二次setName __ ' + name )
- });
- /*
- * 测试
- */
- lulu.setName('nana'); //控制台会输出 您执行一次setName __ nana; 您执行二次setName __ nana;
- lulu.setName('aobama'); //您执行一次setName __ aobama; 您执行二次setName __ aobama;
- lulu.off( 'setName' );
- lulu.setName('lala'); //此时控制台将不会再输出信息
观察者模式 基础使用就是上面所讲,不过不同的框架又在此基础上丰富了功能
如backbone,可以一次添加多个监听事件 lulu.on({ 'setName': fun1, 'getName': fun2 }); 和只执行一次的监听 once。 具体参见 【backbone 源码分析】
Ext提供的功能更多,其中可以 据每次执行监听事件的结果是否为false来判定是否继续执行后面的操作, 除了这个功能较实用外,其它的功能个人认为不常用。
来源转载:http://jiangxiao-2000.iteye.com/blog/1893601
我理解的 js 的观察者模式 Observable的更多相关文章
- 设计模式之观察者模式(Observable与Observer)
设计模式之观察者模式(Observable与Observer) 好久没有写博客啦,之前看完了<设计模式之禅>也没有总结一下,现在回忆一下设计模式之观察者模式. 1.什么是观察者模式 简单情 ...
- RxJava 设计理念 观察者模式 Observable lambdas MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- java中观察者模式Observable和Observer
25.java中观察者模式Observable和Observer 如果想要实现观察者模式,则必须依靠java.util包中提供的Observable类和Observer接口 观察者设计模式 现在很多的 ...
- 理解Node.js的事件轮询
前言 总括 : 原文地址:理解Node.js的事件轮询 Node小应用:Node-sample 智者阅读群书,亦阅历人生 正文 Node.js的两个基本概念 Node.js的第一个基本概念就是I/O操 ...
- js设计模式-观察者模式
定义: 观察者模式又叫发布订阅模式,它定义了对象间的一种一对多的依赖关系.观察者模式让两个对象松耦合地联系在一起,虽然不太清楚彼此的细节,但这不影响他们之间的互相通信. 思路 定义一个对象,在对象中实 ...
- 初步理解require.js模块化编程
初步理解require.js模块化编程 一.Javascript模块化编程 目前,通行的Javascript模块规范共有两种:CommonJS和AMD. 1.commonjs 2009年,美国程序员R ...
- 方便大家学习的Node.js教程(一):理解Node.js
理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时 ...
- 深入理解Node.js中的垃圾回收和内存泄漏的捕获
深入理解Node.js中的垃圾回收和内存泄漏的捕获 文章来自:http://wwsun.github.io/posts/understanding-nodejs-gc.html Jan 5, 2016 ...
- 深入理解three.js中光源
前言: Three.js 是一个封装了 WebGL 接口的非常好的库,简化了 WebGL 很多细节,降低了学习成本,是当前前端开发者完成3D绘图的得力工具,那么今天我就给大家详细讲解下 Three.j ...
随机推荐
- Ubuntu 16.04 安装 VMware-Workstation-12
以前一直使用 Ubuntu + Virtaulbox ,最近测试了 VMware-Workstation-9,性能超过 Virtaulbox-4.2.x,下面是详细步骤: 1 首先准备一个Ubuntu ...
- HDU1879 kruscal 继续畅通工程
继续畅通工程 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- C++中new的解说
new int;//开辟一个存放整数的存储空间,返回一个指向该存储空间的地址(即指针) new int(100);//开辟一个存放整数的空间,并指定该整数的初值为100,返回一个指向该存储空间的地址 ...
- MSSQL 2008错误提示:更改对于登录sa失败
MSSQL 2008错误提示:更改对于登录sa失败: 使用Windows方式登录数据库后,执行以下命令: EXEC sp_password null,"123456"," ...
- 《ASP.NET1200例》<asp:DataList>分页显示图片
aspx页面代码 <asp:DataList ID="dlPhoto" runat="server" Height="137px" W ...
- BestCoder12 1001.So easy(hdu 5058) 解题报告
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5058 (格式有点问题,为了方便阅读---整个复制下来吧) 题目意思:给出两个长度都为 n 的集合你,问 ...
- mybatis异常:Improper inline parameter map format. Should be: #{propName,attr1=val1,attr2=val2}问题分析及解决
转载自:http://blog.csdn.net/jackpk/article/details/44158701 mybatis异常:Improper inline parameter map for ...
- HDU 5805 NanoApe Loves Sequence (思维题) BestCoder Round #86 1002
题目:传送门. 题意:题目说的是求期望,其实翻译过来意思就是:一个长度为 n 的数列(n>=3),按顺序删除其中每一个数,每次删除都是建立在最原始数列的基础上进行的,算出每次操作后得到的新数列的 ...
- Codeforces 390A( 模拟题)
Inna and Alarm Clock Time Limit: 1000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64 ...
- Ajax案例(使用ajax进行加法运算)
此案例功能实现了一边看视频一边进行加法运算,而加法运算时页面不会刷新请求 ajax代码: <script type="text/javascript" src="j ...