javascript实现23种设计模式

参考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
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值