javascript实现23种设计模式

来源:互联网 发布:淘宝店有多少家 编辑:程序博客网 时间:2024/06/06 00:14

参考http://blog.jobbole.com/29454/

1. 单例模式

全局唯一实例

var singleton = function( fn ){    var result;    return function(){        return result || ( result = fn .apply( this, arguments ) );//fn.apply相当于直接调用函数,只是将函数内的this(上下文)改变了    }}var createMask = singleton( function(){return document.body.appendChild( document.createElement('div') ); })

2. 简单工厂模式

由一个方法来决定到底要创建哪个类的实例, 而这些实例经常都拥有相同的接口
参考:http://blog.csdn.net/sinat_29843547/article/details/51131071

//basketball base class  var Baseketball = function(){    this.intro = 'baseketball is hotting at unitedstates';  }  Baseketball.prototype = {    getMember : function(){\      console.log('each team needs five players');    },    getBallSize : function(){      console.log('basketball is big');    }  }  //football base class   var Football = function(){    this.intro = 'football is popular at all of the world';  }  Football = function(){    getMember = function(){    },    getBallSize = function(){    }  }  //sport factory  var SportsFactory = function(name){    switch(name){      case 'NBA':        return new Baseketball();      case 'wordCup':        return new Football();    }  }  //when you want football   var football = SportsFactory('wordCup');  console.log(football);  console.log(football.intro);  football.getMember();  

三 观察者模式(发布者-订阅者模式 )

面试者把简历扔到一个盒子里, 然后面试官在合适的时机拿着盒子里的简历挨个打电话通知结果.(有任何一个事件发生,所有订阅者都会通知,只是匹配不上不执行)

Events = function() {           var listen, log, obj, one, remove, trigger, __this;           obj = {};           __this = this;           listen = function( key, eventfn ) {  //把简历扔盒子, key就是联系方式.             var stack, _ref;  //stack是盒子             stack = ( _ref = obj[key] ) != null ? _ref : obj[ key ] = [];             return stack.push( eventfn );           };           one = function( key, eventfn ) {             remove( key );             return listen( key, eventfn );           };           remove = function( key ) {             var _ref;             return ( _ref = obj[key] ) != null ? _ref.length = 0 : void 0;           };           trigger = function() {  //面试官打电话通知面试者             var fn, stack, _i, _len, _ref, key;             key = Array.prototype.shift.call( arguments );             stack = ( _ref = obj[ key ] ) != null ? _ref : obj[ key ] = [];             for ( _i = 0, _len = stack.length; _i < _len; _i++ ) {               fn = stack[ _i ];               if ( fn.apply( __this,  arguments ) === false) {                 return false;               }             }             return {                listen: listen,                one: one,                remove: remove,                trigger: trigger             }           }

//订阅者

var adultTv = Event();adultTv .listen(  ''play',  function( data ){   alert ( "今天是谁的电影" + data.name );});
//发布者adultTv .trigger(  ''play',  { 'name': '麻生希' }  )

4. 适配器模式

适配器模式的作用很像一个转接口. 本来iphone的充电器是不能直接插在电脑机箱上的, 而通过一个usb转接口就可以了.-

$id = function( id ){  return jQuery( '#' + id )[0];}

5. 代理模式

代理模式的定义是把对一个对象的访问, 交给另一个代理对象来操作.

举一个例子, 我在追一个MM想给她送一束花,但是我因为我性格比较腼腆,所以我托付了MM的一个好朋友来送。

6. 桥接模式

桥接模式的作用在于将实现部分和抽象部分分离开来, 以便两者可以独立的变化。

7. 外观模式

外观模式提供一个高层接口,这个接口使得客户端或子系统更加方便调用。简单讲,就是将小的api封装成大的api

var stopEvent = function( e ){   //同时阻止事件默认行为和冒泡  e.stopPropagation();  e.preventDefault();}

8. 访问者模式

访问者模式先把一些可复用的行为抽象到一个函数(对象)里,这个函数我们就称为访问者(Visitor)。如果另外一些对象要调用这个函数,只需要把那些对象当作参数传给这个函数,在js里我们经常通过call或者apply的方式传递this对象给一个Visitor函数.

var Visitor = {}Visitor .push  =  function(){    return Array.prototype.push.apply( this, arguments );}var obj = {};obj.push = Visitor .push;obj.push( '"first" );alert ( obj[0] )  //"first"alert ( obj.length );  //1

9.策略模式

策略模式的意义是定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。
一个小例子就能让我们一目了然。

$( div ).animate( {"left: 200px"}, 1000, 'linear' );  //匀速运动$( div ).animate( {"left: 200px"}, 1000, 'cubic' );  //三次方的缓动

10. 模版方法模式

模式方法是预先定义一组算法,先把算法的不变部分抽象到父类,再将另外一些可变的步骤延迟到子类去实现。实现思路就是继承,覆盖父类方法

Mammal.prototope.出生 = function(){  '胎生()}Mammal.prototype.成长 = function(){  //再留给子类去实现}Mammal.prototope.衰老 = function(){  自由基的过氧化反应()}Life.prototype.死亡 = function(){ //再留给子类去实现}//再实现一个Dog类var = Dog = function(){}//Dog继承自哺乳动物.Dog.prototype = Mammal.prototype;var dog = new Dog();dog.init();

12. 迭代器模式

迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该方法中的内部表示。
js中我们经常会封装一个each函数用来实现迭代器。
array的迭代器:

forEach = function( ary, fn ){  for ( var i = 0, l = ary.length; i < l; i++ ){    var c = ary[ i ];    if ( fn.call( c, i , c ) === false ){      return false;    }   }}forEach( [ 1, 2, 3 ], function( i, n ){  alert ( i );})

13.组合模式

又叫部分-整体模式,它将所有对象组合成树形结构。使得用户只需要操作最上层的接口,就可以对所有成员做相同的操作。
form.validata函数, 它负责把真正的validata操作分发给每个组合对象.
form.validata函数里面会依次遍历所有需要校验的field. 若有一个field校验未通过, form.validata都会返回false. 伪代码如下.

form.validata = function(){  forEach( fields, function( index, field ){    if ( field.validata() === false  ){       return false;    }  })  return true;}

14. 备忘录模式

备忘录模式在js中经常用于数据缓存. 比如一个分页控件, 从服务器获得某一页的数据后可以存入缓存。以后再翻回这一页的时候,可以直接使用缓存里的数据而无需再次请求服务器。
实现比较简单,伪代码:

var Page = function(){   var page = 1,      cache = {},      data;   return function( page ){      if ( cache[ page ] ){               data =  cache[ page ];               render( data );      }else{               Ajax.send( 'cgi.xx.com/xxx', function( data ){                   cache[ page ] = data;                   render( data );               })      }    }}()

15. 职责链模式

js中的事件冒泡就是作为一个职责链来实现的。一个事件在某个节点上被触发,然后向根节点传递, 直到被节点捕获。

16. 享元模式

享元模式可以提供一些共享的对象以便重复利用. 仔细看下上图, 其实我们一共只需要10个div来显示好友信息,也就是出现在用户视线中的10个div.这10个div就可以写成享元.

 var getDiv = (function(){    var created = [];    var create = function(){          return document.body.appendChild( document.createElement( 'div' ) );    }    var get = function(){         if ( created.length ){              return created.shift();          }else{                return create();           }     }/* 一个假设的事件,用来监听刚消失在视线外的div,实际上可以通过监听滚                                     动条位置来实现 */      userInfoContainer.disappear(function( div ){              created.push( div );        }) })()  var div = getDiv();  div.innerHTML = "${userinfo}";

17. 状态模式

通过这个状态类,可以把散落在世界各地的条件分支集中管理到一个类里,并且可以很容易的添加一种新的状态。而作为调用者,只需要通过暴露的changeState接口来切换人物的状态。

var StateManager = function(){  var currState = 'wait';  var states = {    jump: function( state ){    },    wait: function( state ){    },    attack: function( state ){    },    crouch: function( state ){    },    defense: function( state ){      if ( currState === 'jump'  ){          return false;  //不成功,跳跃的时候不能防御      }    //do something;     //防御的真正逻辑代码, 为了防止状态类的代码过多, 应该把这些逻辑继续扔给真正的fight类来执行.    currState = 'defense'; //  切换状态    }  }  var changeState = function( state ){    states[ state ] && states[ state ]();  }  return {      changeState  : changeState  }}var stateManager = StateManager();stateManager.changeState( 'defense' );
0 0