代理模式
代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。
在我的理解中,es6中的Proxy可以很好的诠释这一设计理念,当然从名称也可以看出来了。
代理模式共有三种:保护代理、虚拟代理、缓存代理
应用场景
保护代理
即代理类对操作进行拦截,对操作进行过滤或处理后,调用真正得实体类进行操作。
例: 每个User类有多种方法,也有一个角色属性,只有管理员能进行某些操作
class User{
constructor(name,code){
this.name = name;
this.code = code;
}
getName(){
return this.name;
}
getCode(){
return this.code;
}
post(){
console.log('发帖子')
}
remove(){
console.log('删帖子')
}
}
class UserProxy{
constructor(user){
this.user = user;
}
getName(){
return this.user.getName();
}
getCode(){
return this.user.getCode();
}
post(){
this.user.post()
}
remove(){
if(this.getCode() != '101'){
console.log('你没有权限')
}else{
this.user.remove()
}
}
}
let user = UserProxy(new User('ljp','001'));
user.remove() // 你没有权限
虚拟代理
虚拟代理把一些开销很大的对象,延迟到真正需要它的时候才去创建,比如合并多个http请求,用缓存类收集请求数据,需要时一起发送
缓存代理
缓存代理可以作为一些开销大的运算结果提供暂时的存储,下次运算时,如果传递进来的参数跟之前一致,则可以直接返回前面存储的运算结果
这样编写也符合设计模式的单一职责原则,一个函数负责计算阶乘,一个函数负责检查缓存。如果需要修改阶乘的算法(如改成135…),只需要修改计算函数。如果需要修改缓存算法也只用改动缓存函数。
function factorial(n){
let sum = 1;
for(let i=1;i<=n;i++){
sum*=i;
}
return sum;
}
function factorialProxy(n){
// 命中缓存
if(factorialProxy.cache[n]!=undefined){
return factorialProxy.cache[n]
}else{
let result = factorial(n);
factorialProxy.cache[n] = result;
return result;
}
}
factorialProxy.cache = {}
console.log(factorialProxy(10))
console.log(factorialProxy(10)) //命中