装饰器参数的形式
@testDec(false) class Demo { } function testDec(isDec) { return function (target) { target.isDec = isDec } } console.log(Demo.isDec);
验证是否是一个真正的装饰器模式需要验证以下几点:
1. 1.将现有对戏那个和装饰器进行分离,两者独立存在 2. 2.符合开放封闭原则
2. 适配器模式
适配器模式:旧接口格式和使用者不兼容,中间加一个适配转换接口。
比如国外的插座跟国内的插座不一样,我们需要买个转换器去兼容。
上代码:
class Adaptee { specificRequest() { return '德国标准的插头'; } } class Target { constructor() { this.adaptee = new Adaptee(); } request() { let info = this.adaptee.specificRequest(); return `${info} -> 转换器 -> 中国标准的插头` } } // 测试 let client = new Target(); client.request();
结果:
德国标准的插头 -> 转换器 -> 中国标准的插头
场景上可封装旧接口:
// 自己封装的ajax,使用方式如下: ajax({ url: '/getData', type: 'Post', dataType: 'json', data: { id: '123' } }).done(function(){ }) // 但因为历史原因,代码中全都是: // $.ajax({...})
这个时候需要一个适配器:
// 做一层适配器 var $ = { ajax: function (options) { return ajax(options) } }
3. 代理模式
代理模式:使用者无权访问目标对象,中间加代理,通过代理做授权和控制。
明星经纪人:比如有个演出,要请明星,要先联系经纪人。
或者理解为:为一个对象提供一个代用品或者占位符,以便控制对它的访问。例如图片懒加载、中介等。
/** * pre:代理模式 * 小明追求A,B是A的好朋友,小明比不知道A什么时候心情好,不好意思直接将花交给A, * 于是小明将花交给B,再由B交给A. */ // 花的类 class Flower{ constructor(name){ this.name = name } } // 小明拥有sendFlower的方法 let Xioaming = { sendFlower(target){ var flower = new Flower("玫瑰花") target.receive(flower) } } // B对象中拥有接受花的方法,同时接收到花之后,监听A的心情,并且传入A心情好的时候函数 let B = { receive(flower){ this.flower =flower A.listenMood(()=>{ A.receive(this.flower) }) } } // A接收到花之后输出花的名字 let A = { receive(flower){ console.log(`A收到了${flower.name} `) // A收到了玫瑰花 }, listenMood(func){ setTimeout(func,1000) } } Xioaming.sendFlower(B)
虚拟代理用于图片的预加载
图片很大,页面加载时会空白,体验不好,所以我们需要个占位符,来短暂替代这个图片,等图片加载好了放上去。
let myImage = (function(){ let img = new Image document.body.appendChild(img) return { setSrc:(src)=>{ img.src = src } } })() let imgProxy =(function(){ let imgProxy = new Image // 这个地方我使用了setTimeout来增强演示效果,否则本地加载太快,根本看不到。 imgProxy.onload=function(){ setTimeout(()=>{ myImage.setSrc(this.src) },2000) } return (src)=>{ myImage.setSrc("../../img/bgimg.jpeg") imgProxy.src=src } })() imgProxy("../../img/background-cover.jpg")
ES6 Proxy
其实在ES6中,已经有了Proxy,这个内置的函数。我们来用一个例子来演示一下他的用法。这是一个明星代理的问题。
let star={ name : "张XX", age:25, phone : "1300001111" } let agent = new Proxy(star, { get:function(target,key){ if(key === "phone"){ return "18839552597" }else if(key === "name"){ return "张XX" }else if(key === "price"){ return "12W" }else if(key === "customPrice"){ return target.customPrice } }, set:function(target,key,value){ if(key === "customPrice"){ if(value < "10"){ console.log("太低了!!!") return false }else{ target[key] = value return true } } } } ) console.log(agent.name) console.log(agent.price) console.log(agent.phone) console.log(agent.age) agent.customPrice = "12" console.log(agent) console.log(agent.customPrice)
设计原则验证
代理类和目标类分离,隔离开目标类和使用者
符合开放封闭原则