女王控的博客

JS中设计模式简单介绍

单例模式

var singleton = function( fn ){
    var result;
    return function(){
        return result || ( result = fn.apply( this, arguments ) );
    }
}
var createMask = singleton( function(){
    return document.body.appendChild( document.createElement('div') );
})

简单工厂模式

这段代码来自es5的new和构造器的相关说明,可以看到, 所谓的new本身只是一个对象的复制和改写过程, 而具体会生成什么是由调用ObjectFactory时传进去的参数所决定的。

function A( name ){
    this.name = name;
}
function ObjectFactory(){
    var obj = {},
    Constructor = Array.prototype.shift.call( arguments );
    obj.__proto__ =  typeof Constructor.prototype === 'number'  ? Object.prototype : Constructor.prototype;
    var ret = Constructor.apply( obj, arguments );
    return typeof ret === 'object' ? ret : obj;
}
var a = ObjectFactory( A, 'svenzeng' );
alert ( a.name );  //svenzeng

观察者模式

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 ] = [];
        console.log(key,stack,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 = Events();
console.log(adultTv);
adultTv.listen( 'play',  function( data ){
   alert ( "今天是谁的电影" + data.name );
});
adultTv.listen( 'play',  function( data ){
   alert ( "今天是" + data.name );
});
//发布者
adultTv.trigger( 'play',  { 'name': '广告' }  )
adultTv.trigger( 'play',  { 'name': '麻生' }  )

适配器模式

my.category = adapterCategory ( afu.category );
$id = function( id ){
  return jQuery( '##' + id )[0];
}

代理模式

var keyMgr = keyManage();
 
keyMgr.listen( 'change', proxy( function( keyCode ){
    console.log( keyCode );  //前下前+拳
)} );

var request = Ajax.get( 'cgi.xx.com/xxx' );
request.send();
request.done(function(){

});

桥接模式

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 ( n*2 )
})
 
forEach( [1,2,3], function( i, n ){
  alert ( n*3 )
})

外观模式

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

访问者模式

function ArrayPush() {  
    var n = TO_UINT32( this.length );
    var m = %_ArgumentsLength();    
    for (var i = 0; i < m; i++) {    
        this[i+n] = %_Arguments(i);//属性拷贝  
    }  
    this.length = n + m;    //修正length  
    return this.length;
}
// 访问者模式先把一些可复用的行为抽象到一个函数(对象)里,
// 这个函数我们就称为访问者(Visitor)。
// 如果另外一些对象要调用这个函数,只需要把那些对象当作参数传给这个函数,
// 在js里我们经常通过call或者apply的方式传递this对象给一个Visitor函数
var obj = {};
obj.push = function(){
    return Array.prototype.push.apply( this, arguments );
};
obj.push( "first" );
alert ( obj[0] )  //"first"
alert ( obj.length );  //1

策略模式

nameInput.addValidata({
   notNull: true,
   dirtyWords: true,
   maxLength: 30
})
// 而notNull,maxLength等方法只需要统一的返回true或者false,来表示是否通过了验证。
validataList = {
  notNull: function( value ){
     return value !== '';
  },
  maxLength: function( value, maxLen ){
     return value.length() > maxLen;
  }
}

var validator = {
    // 所有可以的验证规则处理类存放的地方,后面会单独定义
    types: {},
    // 验证类型所对应的错误消息
    messages: [],
    // 当然需要使用的验证类型
    config: {},
    // 暴露的公开验证方法
    // 传入的参数是 key => value对
    validate: function (data) {
        var i, msg, type, checker, result_ok;
        // 清空所有的错误信息
        this.messages = [];
        for (i in data) {
            if (data.hasOwnProperty(i)) {
                type = this.config[i];  // 根据key查询是否有存在的验证规则
                checker = this.types[type]; // 获取验证规则的验证类
                if (!type) {
                    continue; // 如果验证规则不存在,则不处理
                }
                if (!checker) { // 如果验证规则类不存在,抛出异常
                    throw {
                        name: "ValidationError",
                        message: "No handler to validate type " + type
                    };
                }
                result_ok = checker.validate(data[i]); // 使用查到到的单个验证类进行验证
                if (!result_ok) {
                    msg = "Invalid value for *" + i + "*, " + checker.instructions;
                    this.messages.push(msg);
                }
            }
        }
        return this.hasErrors();
    },
    // helper
    hasErrors: function () {
        return this.messages.length !== 0;
    }
};

// 验证给定的值是否不为空
validator.types.isNonEmpty = {
    validate: function (value) {
        return value !== "";
    },
    instructions: "传入的值不能为空"
};

// 验证给定的值是否是数字
validator.types.isNumber = {
    validate: function (value) {
        return !isNaN(value);
    },
    instructions: "传入的值只能是合法的数字,例如:1, 3.14 or 2010"
};

// 验证给定的值是否只是字母或数字
validator.types.isAlphaNum = {
    validate: function (value) {
        return !/[^a-z0-9]/i.test(value);
    },
    instructions: "传入的值只能保护字母和数字,不能包含特殊字符"
};

var data = {
    first_name: "Tom",
    last_name: "Xu",
    age: "unknown",
    username: "TomXu"
};
//该对象的作用是检查验证类型是否存在
validator.config = {
    first_name: 'isNonEmpty',
    age: 'isNumber',
    username: 'isAlphaNum'
};

validator.validate(data);

if (validator.hasErrors()) {
    console.log(validator.messages.join("\n"));
}

模版方法模式

var Life = function(){
}
Life.prototype.init = function(){
   this.DNA复制();
   this.出生();
   this.成长();
   this.衰老();
   this.死亡();
}
this.prototype.DNA复制 = function(){
  &*$%&^%^&(&(&(&&(^^(*)  //看不懂的代码
}
Life.prototype.出生 = function(){
}
Life.prototype.成长 = function(){
}
Life.prototype.衰老 = function(){
}
Life.prototype.死亡 = function(){
}
var Mammal = function(){
}
Mammal.prototype = Life.prototype;   //继承Life

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();

中介者模式

var mode1 = Mode.create(),  mode2 = Mode.create();
var view1 = View.create(),   view2 = View.create();
var controler1 = Controler.create( mode1, view1, function(){
  view1.el.find( 'div' ).bind( 'click', function(){
    this.innerHTML = mode1.find( 'data' );
  } )
})
var controler2 = Controler.create( mode2, view2, function(){
  view1.el.find( 'div' ).bind( 'click', function(){
    this.innerHTML = mode2.find( 'data' );
  } )
})

迭代器模式

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 );
})

组合模式

var allNodes = document.getElementsByTagName("\*");
var len = allNodes.length;
while( len-- ){
  allNodes.unbind("\*");
}
form.validata = function(){
  forEach( fields, function( index, field ){
    if ( field.validata() === false  ){
       return false;
    }
  })
  return true;
}

备忘录模式

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 );
        })
      }
    }
}()

职责链模式

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

享元模式

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}";

状态模式

if ( state === 'jump' ){
   if ( currState === 'attack' || currState === 'defense' ){
     return false;
   }
}else if ( state === 'wait' ){
   if ( currState === 'attack' || currState === 'defense' ){
     return true;
   }
}

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%