热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

04代理,迭代器

代理模式为一个对象提供一个代用品或占位符。以便控制对他的访问;面向对象设计原则-单一职责原则就一个类(对象,函数)而言,应该仅有一个引起他变化的原因;(低耦合)代理和本体借口的一致性当不需要代理的时候

代理模式

  • 为一个对象提供一个代用品或占位符。以便控制对他的访问;
面向对象设计原则-单一职责原则
  • 就一个类(对象,函数)而言,应该仅有一个引起他变化的原因;(低耦合)

代理和本体借口的一致性

  • 当不需要代理的时候可以替换回本体

保护代理

  • 过滤请求;可以用于控制不同权限对象对目标对象的访问

虚拟代理

  • 把一些开销很大的对象,延迟到真正需要的时候才创建;
  • 实现图片预加载
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'));

推荐阅读
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • 一、什么是闭包?有什么作用什么是闭包闭包是定义在一个函数内部的函数,它可以访问父级函数的内部变量。当一个闭包被创建时,会关联一个作用域—— ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • VueCLI多页分目录打包的步骤记录
    本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
author-avatar
踏山321
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有