我理解的 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 ...
随机推荐
- nyoj 20
http://acm.nyist.net/JudgeOnline/message.php?msg=已提交&url=status.php%3Fpid%3D20&second=0 #inc ...
- thinkphp 前台html调用函数 格式化输出
仅仅是输出变量并不能满足模板输出的需要,内置模板引擎支持对模板变量使用调节器和格式化功能,其实也就是提供函数支持,并支持多个函数同时使用.用于模板标签的函数可以是PHP内置函数或者是用户自定义函数,和 ...
- 【云计算】ubuntu下docker安装配置指南
Docker Engine安装配置 以下描述仅Docker在Ubuntu Precise 12.04 (LTS).Ubuntu Trusty 14.04 (LTS).Ubuntu Wily 15.10 ...
- There is no getter for property named 'purchaseApplyId' in 'class java.lang.Long'
mapper.xml: <delete id="deleteByPurchaseAppyId" parameterType="Long"> < ...
- Java for LeetCode 147 Insertion Sort List
Sort a linked list using insertion sort. 解题思路: 插入排序,JAVA实现如下: public ListNode insertionSortList(List ...
- window.open()读取本地图片简单使用总结
最近做了一个项目,需要读取本地图片出来,问了一些人,感觉在数据库中存取路径比较合适,故做此方法. 后台查询出来的路径
- 【Qt】学习笔记(一)
1.setupUi(this) : setupUi(this)是由.ui文件生成的类的构造函数这个函数的作用是对界面进行初始化它按照我们在Qt设计器里设计的样子把窗体画出来 setupUi(this) ...
- dbVisualizer破解
下载dbvis.puk,替换C:\Program Files\DbVisualizer\lib\dbvis.jar中的文件. 替换后打开选手动的key:下载地址dbvis.license
- ytu 1985:C语言实验——保留字母(水题)
C语言实验——保留字母 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 136 Solved: 59[Submit][Status][Web Board] ...
- HDU 4258 Covered Walkway 斜率优化DP
Covered Walkway Problem Description Your university wants to build a new walkway, and they want at ...