本文共 2421 字,大约阅读时间需要 8 分钟。
使用者无权访问目标对象
中间加代理,通过代理做授权和控制
传统 UML 类图
简化后的 UML 类图
class ReadImg { constructor(fileName) { this.fileName = fileName this.loadFromDisk() // 初始化即从硬盘中加载,模拟 } display() { console.log('display...' + this.fileName) } loadFromDisk() { console.log('loading...' + this.fileName) }}class ProxyImg { constructor(fileName) { this.realImg = new ReadImg(fileName) // 实例化 ReadImg 类 } display() { this.realImg.display() }}// 测试let proxyImg = new ProxyImg('1.png')proxyImg.display()
$('#div1').click(function () { // this 符合期望 $(this).addClass('red') })$('#div1').click(function () { setTimeout(function () { // this 不符合期望 $(this).addClass('red') }, 1000)});
// 可以用如下方式解决$('#div1').click(function () { var _this = this setTimeout(function () { // _this 符合期望 $(_this).addClass('red'); }, 1000)});
// 但推荐使用 $.proxy 解决,这样就少定义一个变量$('#div1').click(function () { setTimeout($.proxy(function () { // this 符合期望 $(this).addClass('red') }, this), 1000)});
// 明星let star = { name: 'xxx', age: 24, phone: 'star: 13900001111'}// 经纪人let agent = new Proxy(star, { get: function (target, key) { // 代理的接口必须和原生的一样 if (key === 'phone') { // 返回经纪人自己的电话 return 'agent: 16899992222' } if (key === 'price') { // 明星不报价,经纪人报价 return 120000 } return target[key] }, set: function (target, key, val) { if (key === 'customPrice') { if (val < 100000) { // 最低10w throw new Error('价格太低') } else { target[key] = val return true } } }})// 测试console.log(agent.name);console.log(agent.age);console.log(agent.phone);console.log(agent.price);agent.customPrice = 90000console.log('agent.customPrice', agent.customPrice);
代理类和目标类分离,隔离开目标类和使用者
符合开放封闭原则
适配器模式
不同的接口
(如不同版本的插头)目标类老旧或格式不一样,不能用
代理模式
一模一样的接口
无权使用目标类
装饰器模式
扩展功能,原有功能不变且可直接使用
扩展功能与原有功能并不冲突
代理模式
显示原有功能,但是经过限制或者阉割之后的
转载地址:http://hcqwi.baihongyu.com/