js常用的设计模式 (自己整理笔记)
①: 简单的工厂模式(SportsFactory就是基类)
//工厂不只是可以返回一个对象
var SportsFactory=function (name) {
switch (name){
case 'NBA':
return new Basketball()
case 'wordCup':
return new Football()
case 'FrenchOpen':
return new Tennis()
}
}
function Basketball() {}
function Football() {}
function Tennis() {}
②:建造者模式 (将创造出来的三个实例就联系起来了)
function Person(name, work) {
var _person = new Human();
_person.name = new Named(name);
_person.work = new Work(work);
return _person
}
然后再去写构造函数,函数里有什么需求再自己去添加。
function Human(param) {}
function Named(param) {}
function Work (param) {}
③:原型模式(常用)
//定义基类
function baseClass(imgArr,container) {
this.imgArr = imgArr;
this.container = container;
}
baseClass.prototype={
createImage:function () {}
}
//组合继承基类
function SlideLoopImg(imgArr,container) {
baseClass.call(this,imgArr,container)
}
SlideLoopImg.prototype = new baseClass()
SlideLoopImg.prototype.changeImage=function () {}
//再组合继承基类
function ......
④:单例模式(只允许实例化一次的对象类。单例模式常用来定义命名空间)
对象里面有很多对象
var A = {
UTIL: {
util_methond1: function () {},
util_methond2: function () {}
},
Tool: {
tool_method1: function () {},
tool_method2: function () {}
},
Ajax: {
get: function () {},
post: function () {}
}
}
//调用 A.UTIL.util_methond1()
⑧:状态类方法 不用写好多if else 不好维护 if(action=='state1')..
var ResultState = function () {
var states = {
state0: function () {
console.log('第一种对象');
},
state1: function () {
console.log('第二种对象');
},
state2: function () {
console.log('第三种对象');
},
state3: function () {
console.log('第四种对象');
}
}
function show(result) {
//获取某一种状态并执行其对应的方法
states[result] && states[result]()
}
return {
showKey:show
}
}();
ResultState.showKey('state1')
⑨:策略模式:!! 将一组算法封装起来,封装的算法就有独立性。
var InputStrategy = function () {
var strategy = {
//是否是数字
number: function (value) {
return /^[0-9]+(\.[0-9]+)?$/.test(value) ? '' : '请输入数字'
},
phone: function (value) {
return /^\d{3}\-\{8}$|^\d{4}\-\d{7}$/.test(value) ? '' : '请输入正确格式'
}
}
return {
check: function (type, value) {
//去除首尾空白符
value = value.replace(/^\s+|\s+$/g, '');
return strategy[type] ? strategy[type](value) : '没有该类型请添加'
},
addStrategy: function (type, fn) {
strategy[type] = fn;
}
}
}();
$('button').click(function () {
$('div').html(InputStrategy.check('number',$('input').val()))
})
⑩ 命令模式:
//命令模式用于解耦,使用canvas的时候辉导演内置方法,这在多人开发过程中的耦合度比较高,一个人把内置方法改了,谁也别用了
//命令模式是讲执行的命令封装,解决命令的发起者与命令的执行者之间的耦合
var CanvasCommand = (function () {
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
var Action = {
fillStyle: function (c) {
ctx.fillStyle = c;
},
fillRect: function (x, y, width, height) {
ctx.fillRect(x, y, width, height)
}
//...等等方法
}
return {
excute: function (msg) {
if (!msg) {
return;
};
if (msg.length) {
//遍历多个命令
for (var i = 0, len = msg.length; i < len; i++) {
arguments.callee(msg[i])
}
} else {
msg.param=Object.prototype.toString.call(msg.param)==='[object Array]'?msg.param:[msg.param];
//Action内部调用的方法可能引用this,为保证作用域中this指向正确,所以传入Action
Action[msg.command].apply(Action,msg.param)
}
}
}
})()
十一: 委托模式
// 完整的事件流是从事件捕获开始,到触发该事件,再到事件冒泡三个阶段。所以子元素有多个的时候可以将事件委托给更高层面的父元素去绑定执行。
父元素再冒泡到子元素,就不用捕获了。
//委托可以对未来元素添加事件,是因为在未来此元素是存在的,当未来发生冒泡的时候次元素的存在的,所以事件能够触发
$('ul').on('click','li',function (e) {
console.log(e.target);
})
十三:节流模式
/*
* 函数节流方法
* @param Function fn 延时调用函数
* @param Number delay 延迟多长时间
* @param Number atleast 至少多长时间触发一次
* @return Function 延迟执行的方法
*/
var throttle = function (fn, delay, atleast) {
var timer = null;
var previous = null;
return function () {
// new Date().valueOf()和 +new Date()是一样的
var now = new Date().valueOf();
//第一次赋值
if ( !previous ) previous = now;
//过了atleast这个时间再点击当然重新计算
if ( now - previous > atleast ) {
fn();
// 重置上一次开始时间为本次结束时间
previous = now;
// 多次点击清除计时器
} else {
clearTimeout(timer);
timer = setTimeout(function() {
fn();
}, delay);
}
}
};
function testFn() {
console.log(3);
}
$('div').on('click',throttle(testFn, 600,1000))