js设计模式(下)
链模式
链模式是实现链式调用的主要方法,通过在自身方法中返回自身的方式,在一个对象连续多次调用自身方法可以简化写法。这种链式调用在很多库和框架如jquery/zepto中频繁的被使用。
委托模式
当多个对象需要处理同一请求时,可以将这些请求交由另一个对象统一处理。
例:事件委托
数据访问对象模式
数据访问对象模式主要是用来抽象和封装一个对象来对数据源进行访问和存储,这样可以方便对数据的管理,以及避免数据间重复,覆盖等问题出现。
例:定义一个保存数据的方法
/**
* {
* nameSpace|key: expire|value
* }
*/
var DataVisitor = function(nameSpace, splitSign){
// nameSpace用来拼接key
this.nameSpace = nameSpace
this.splitSign = splitSign || '|';
}
DataVisitor.prototype = {
status: {
SUCCESS: 0,
FAIL: 1,
// 溢出
OVERFLOW: 2,
TIMEOUT: 3
},
// 拼接一个key
getKey: function(key){
return this.nameSpace + this.splitSign + key
},
// 存储键值对到localStorage
set: function(key, value, fn, expire){
var status = this.status.SUCCESS
key = this.getKey(key)
expire = typeof expire === 'number' ? expire + Date.now() : -1
try {
window.localStorage.setItem(key, expire + this.splitSign + value)
} catch (error) {
status = this.status.OVERFLOW
}
fn && fn.call(this, status, key, value)
return value;
},
// 读取
get: function(key, fn){
key = this.getKey(key)
this.status = this.status.SUCCESS
var value = window.localStorage.getItem(key)
if(value){
var index = value.indexOf(this.splitSign)
time = value.slice(0, index)
if(time > new Date().getTime() || -1){
value = value.slice(index + this.splitSign.length)
}else{
value = null
status = this.status.TIMEOUT
window.localStorage.removeItem(key)
}
}else{
status = this.status.FAIL
}
fn && fn.call(this, status, key, value)
return value
},
// 删除
remove: function(key){
var status = this.status.FAIL
key = this.getKey(key)
value = window.localStorage.getItem(key)
if(value){
status = this.status.SUCCESS
window.localStorage.removeItem(key)
}
return status
}
}
// 测试
var learnInfo = new DataVisitor('learn')
learnInfo.set('ok', 'value')
等待者模式
通过对多个异步进程的监听,对未来事件进行统一管理。
例:实现waiter对象调用when传异步事件,返回值调用done或fail执行回调函数
- waiter.when(异步事件1,异步事件2...).done(fn).fail(fn)
function Waiter(){
// 存放异步事件
var dfd = [];
// 存放成功的回调
var doneArr = [];
// 存放失败的回调
var failArr = [];
// 保存Defer
this.when = function(){
// 获取arguments是类数组对象
dfd = Array.from(arguments)
// 删除不满足条件的Defer
for(var i = dfd.length - 1; i >= 0; i--){
var d = dfd[i];
if(!d || d.rejected || d.resolved || !(d instanceof Defer)){
dfd.splice(i, 1)
}
}
return this;
}
// 保存成功的回调
this.done = function(){
// 拿到参数(成功回调)
var args = Array.prototype.slice.call(arguments)
doneArr = doneArr.concat(args);
return this;
}
// 保存失败的回调,控制执行成功或失败的回调函数
this.fail = function(){
// 拿到参数(失败回调)
var args = Array.prototype.slice.call(arguments)
failArr = failArr.concat(args);
return this;
}
// 控制成功失败状态
this.Defered = function(){
return new Defer();
}
var Defer = function(){
// 状态值
this.resolved = false;
this.rejected = false
}
Defer.prototype = {
resolve: function(){
this.resolved = true;
for(var i = 0; i < dfd.length; i++){
// 有一个resolved不为true就不执行回调
if(!dfd[i].resolved) return;
}
// 全部完成
// 执行成功回调函数
_exec(doneArr);
},
reject: function(){
this.rejected = true
// 失败回调
_exec(failArr);
}
}
// 遍历成功或者失败的回调,并调用
function _exec(arr){
for(var i = 0; i < arr.length; i++){
arr[i] && arr[i]();
}
}
}
使用
var waiter = new Waiter()
// 异步函数1
var async1 = function(){
var dfd = waiter.Defered()
setTimeout(() => {
console.log('async dome')
dfd.resolve()
// dfd.reject()
}, 1000);
return dfd;
}
// 异步函数2
var async2 = function(){
var dfd = waiter.Defered()
setTimeout(() => {
console.log('async2 dome')
dfd.resolve()
}, 2000);
return dfd;
}
waiter.when(async1(), async2()).done(function(){
console.log('success')
}).fail(function(){
console.log('fail');
})
结果
1
1
1
1
1
1
1
1
1
1