代理模式
为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用.
-
图例
- 代码实现
class Google{
get(url){
return `google:${url}`
}
}
class Proxy{
constructor(){
this.google=new Google()
}
get(url){
return this.google.get(url)
}
}
let proxy=new Proxy();
let result=proxy.get('http://www.google.com');
console.log(result) //google:http://www.google.com
- 缓存代理
//计算阶乘 普通方式
function mult(n){
if(n<=1){
return 1
}else{
return n*mult(n-1)
}
}
let result=mult(5); //120
console.log(result)
//缓存代理
let result=(function(){
return function(n){
let cache={}
function mult(n){
if(cache[n]!==undefined){
return cache[n];
}
let result
if(n<=1){
result=1
}else{
result= n*mult(n-1)
}
cache[n]=result;
console.log(cache) //{ '1': 1, '2': 2, '3': 6, '4': 24, '5': 120 }
return result
}
return mult(n)
}
})()
console.log(result(5))
- 虚拟缓存
let myImage=(function(){
let img=document.createElement('img');
document.body.appendChild(img);
return {
setSrc:function(src){
img.src=src
}
}
})()
let proxyImage=(function(){
let image=new Image;
image.onload=function(){
myImage.setSrc(this.src)
}
return {
setSrc:function(src){
myImage.setSrc('loading.gif')
//赋值整上
image.src=src
}
}
})()
proxyImage.setSrc( '1.jpg' );
- es6 Proxy(代理)
// 不能直接修改children 通过mither代理 间接修改children
let children={age:18,name:'wx'};
let mither=new Proxy(children,{
get(target,key){
if(key=='age'){
return target[key]+2
}else{
return target[key]
}
},
set(target,key,value){
return target[key]=value
}
})
console.log(mither.age) //20
mither.height=123
console.log(children) // { age: 18, name: 'wx', height: 123 }
- 应用场景
1.事件委托
<ul id="ulList">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
let ulList=document.querySelector("#ulList");
ulList.addEventListener('click',function(event){
alert(event.target.innerHTML)
})
</script>
2.jquery.proxy
$('#ulList').click(function(){
$(this).addClass('red')
})
// this指向改变
$('#ulList').click(function() {
setTimeout(function() {
// Problem! In this function "this" is not our element!
$(this).addClass('red')
}, 1000);
})
//$.proxy
$('#ulList').click(function() {
setTimeout($.proxy(function() {
$(this).addClass('red')
},this), 1000);
})
$.proxy的实现
window.$.proxy=function(fn,arg){
fn.call(arg,arguments)
}
$('#ulList').click(function() {
setTimeout($.proxy(function() {
$(this).addClass('red')
},this), 1000);
})
3.防抖
function debounce(fn,wait){
let timeout=null;
if(timeout!==null) clearTimeout(timeout)
timeout=setTimeout(() => {
fn.apply(this,arguments);
timeout=null
}, wait);
}
function handle() {
console.log(new Date());
}
window.addEventListener('scroll',debounce(handle,1000))
代理模式 | 区别 |
---|---|
代理模式vs适配器模式 | 适配器模式可以提供不同的接口,代理模式必须提供一摸一样的接口 |
代理模式vs装饰器模式 | 装饰器模式原来的功能不变可以继续使用,代理模式改变原有的功能 |
优点 |
---|
1.职责清晰:真实的角色就是实现实际的[业务逻辑],不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。 |
2.代理对象可以在客户端和目标对象之间起到中介作用,这样起到了中介保护目标对象的作用 |
3.高扩展性 |