作者:踏山321 | 来源:互联网 | 2023-09-25 16:53
代理模式为一个对象提供一个代用品或占位符。以便控制对他的访问;面向对象设计原则-单一职责原则就一个类(对象,函数)而言,应该仅有一个引起他变化的原因;(低耦合)代理和本体借口的一致性当不需要代理的时候
代理模式
- 为一个对象提供一个代用品或占位符。以便控制对他的访问;
面向对象设计原则-单一职责原则
- 就一个类(对象,函数)而言,应该仅有一个引起他变化的原因;(低耦合)
代理和本体借口的一致性
保护代理
- 过滤请求;可以用于控制不同权限对象对目标对象的访问
虚拟代理
- 把一些开销很大的对象,延迟到真正需要的时候才创建;
- 实现图片预加载
var myImage = (function() {
var imgNode = document.createElement('img');
document.body.appendChild(imgNode);
return function(src) {
imgNode.src = src;
};
})();
var proxyImage = (function() {
var img = new Image;
img.Onload= function() {
myImage(this.src);
};
return function(src) {
myImage('picture/loading.jpg');
img.src = src;
}
})();
proxyImage('http://tp3.sinaimg.cn/1805666510/180/5718258464/1');
var synchrOnousFile= function (id) {
console.log('开始同步 ' + id);
};
var proxySynchrOnousFile= (function() {
var cache = [], timer;
return function(id) {
cache.push(id);
if(timer)
return;
timer = setTimeout(function() {
synchronousFile(cache.join(','));
clearTimeout(timer);
timer = null;
cache.length = 0;
}, 2000); //2秒延迟后一次性处理
};
})();
var checkbox = document.getElementsByTagName('input');
for(var i = 0, c; c = checkbox[i++];) {
c.Onclick= function() {
if(this.checked === true)
proxySynchronousFile(this.id);
}
};
在堕性加载中的应用
var miniCOnsole= (function(){
var cache = [];
var handler = function( ev ){
if ( ev.keyCode === 13 ){ //enter
var script = document.createElement( 'script' );
script.Onload= function(){
for ( var i = 0, fn; fn = cache[ i++ ]; ){
fn();
}
};
script.src = 'log.js';
document.getElementsByTagName( 'head' )[0].appendChild(script);
document.body.removeEventListener( 'keydown', handler );
}
};
document.body.addEventListener( 'keydown', handler, false );
return {
log: function(){
var args = arguments;
cache.push( function(){
return miniConsole.log.apply( miniConsole, args ); //缓存,当真正加载log.js再执行;
});
}
}
})();
miniConsole.log(0);
miniConsole.log(1);
//按下enter
// log.js 代码
miniCOnsole= {
log: function(){
// 真正代码略
console.log( Array.prototype.join.call( arguments ) );
}
};
缓存代理
var mult = function () {
var a = 1;
for(var i = 0, len = arguments.length; i a = a * arguments[i];
return a;
};
var proxyMult = (function() {
var cache = {};
return function() {
var args = [].join.call(arguments, ',');
if(args in cache)
return cache[args]
return cache[args] = mult.apply(this, arguments);
};
})();
proxyMult(3,6,8);
- 用于ajax异步请求: 如分页实现时讲数据缓存,下次请求同一页再输出;
利用高阶函数动态创建代理
- 如将上面的
proxyMult
修改,使以后类似计算的缓存代理都用同一个函数产生
var createProxyFactory = function(fn) {
var cache = {};
return function() {
var args = [].join.call(arguments, ',');
if(args in cache)
return cache[args];
return cache[args] = fn.apply(this, arguments);
}
};
var proxyMult = createProxyFactory(mult);
其他代理
迭代器模式
- 顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示的方法;
- 现在流行的大部分语言都有内置的迭代器实现;JS中如
Array.prototype.forEach
内部迭代器
var each = function (arr, callback) {
for(var i = 0, len = arr.length; i callback.call(arr, i, arr[i]); //这里可以修改对象
};
each([1,2,3], function(index, value) {
console.log(this,index,value);
});
外部迭代器
- 必须显示地请求迭代下一个元素;增加了复杂度,但也增强累迭代器的灵活性;可以手工控制迭代过程;
var Iterator = function(obj) {
var current = 0, len = obj.length;
var next = function() {
current++;
}
var isDOne= function() {
return current >= len; //如果length会自动修改那直接使用
}
var getCurrentIten = function() {
return obj[current];
}
return {
next: next,
isDone: isDone,
getCurrentIten: getCurrentIten
}
};
//一个比较数组相等的例子
var compare = function(iterator1, iterator2) {
while(!iterator1.isDone() || !iterator2.isDone()) {
if(iterator1.getCurrentIten() !== iterator2.getCurrentIten())
throw new Error('不相等');
iterator1.next();
iterator2.next();
}
console.log('相等');
};
compare(Iterator([0,1,2]), Iterator([0,1,2]));
另一个迭代器实现
var Iterator = function (items, container) {
var cOntainer= container && document.getElementById(container) || document.body,
items = container.getElementsByTagName(items),
len = items.length,
index = 0,
splice = [].splice;
return {
first: function () {
index = 0;
return items[index];
},
second: function () {
index = len - 1;
return items[index];
},
pre: function () {
if(--index > 0)
return items[index];
else {
index = 0;
return null;
}
},
next: function () {
if(++index return items[index]
else {
index = len - 1;
return null;
}
},
get: function (num) {
index = num >= 0 ? num % len : num % len + len;
return items[index];
},
dealEach: function (fn) {
var args = splice.call(arguments, 1);
for(var i = 0; i fn.apply(items[i], args);
}
},
dealItem: function (num, fn) {
fn.apply(this.get(num), splice.call(arguments, 2))
},
exclusive: function (num, allFn, numFn) {
this.dealEach(allFn);
if(Object.prototype.toString.call(num) === '[object Array]') {
for(var i = 0, l = num.length; i this.dealItem(num[i], numFn);
}
} else {
this.dealItem(num, numFn);
}
}
}
};
var demo = new Iterator('li', 'container');
console.log(demo.first());
console.log(demo.pre());
console.log(demo.next());
console.log(demo.get(3));
demo.dealEach(function(text, color) {
this.innerHTML = text;
this.style.background = color;
}, 'test', 'pink');
demo.exclusive([2,3], function () {
this.innerHTML = '被排除的';
this.style.background = 'green';
}, function () {
this.innerHTML = '被选中的';
this.style.background = 'red';
})
迭代类数组和字面量对象
- 实际上只要聚合对象拥有
length
属性并可以下标访问就可以被迭代
应用例子
- 比如一个功能里使用
try-catch,if-else
等根据实际情况尝试不同的执行函数;
- 可以将所有要尝试的函数单独分开并设置尝试执行失败返回
false
;
- 将所有要尝试的函数通过高迭代器执行,以后增加新的执行函数,只要按照一定顺序迭代就可以;
var iterator = function() {
for(var i = 0, fn; fn = arguments[i++];) {
var result = fn();
if(result !== false)
return result;
}
};
iterator(fn1, fn2, fn3, fn4);
同步变量迭代器
//同步变量
var A = {
common: {},
client: {
user: {
username: '',
uid: ''
}
},
server: {}
};
//同步变量迭代取值器
var AGetter = function (key) {
if(!A) return;
var result = A;
key = key.split('.');
for(var i = 0, l = key.length; i if(result[key[i]] !== undefined) {
result = result[key[i]];
} else {
return;
}
}
return result;
};
//同步变量迭代赋值器
var ASetter = function (key, val) {
if(!A) return;
var result = A;
key = key.split('.');
for(var i = 0, l = key.length; i if (result[key[i]] === undefined) {
result[key[i]] = {};
}
if (!(result[key[i]] instanceof Object)) {
throw new Error('A. ' + key.splice(0, i + 1).join('.') + ' is not Object');
return false;
}
result = result[key[i]];
}
return result[key[i]] = val;
};
console.log(AGetter('client.user.username'));
console.log(ASetter('client.server.new', 'on'));