设计模式-代理模式

介绍

  • 使用者无权访问目标对象
  • 中间加代理,通过代理做授权和控制

UML类图

  • 传统UML类图

  • 简化UML

代码演示

js 复制代码
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)
    }
    display() {
        this.readImg.display()
    }
}

// test 
let proxyImg = new ProxyImg('1.png')
proxyImg.display()

场景

网页事件代理

js 复制代码
<div id="div1">
    <a href="#">a1</a>
    <a href="#">a2</a>
    <a href="#">a3</a>
    <a href="#">a4</a>
</div>
<button>点击增加一个a标签</button>

<script>
var div1 = document.getElementById('div1')
div1.addEventListener('click', function(e) {
    var target = e.target
    if (e.nodeName === 'A') {
        alert(target.innerHTML)
    }
})
</script>

jQuery.$.proxy代理

js 复制代码
$('#div1').click(function() {
    // this 符合期望
    $(this).addClass('red')
})
$('#div1').click(function() {
    setTimeout(function() {
        // this 不符合期望
        $(this).addClass('red')
    }, 1000);
});

// 可以用如下方式解决
$('#div').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);                                                         
})

// 上面函数的另一种写法
$('#div1').click(function() {
    var fn = function() {
        $(this).css('background-color', 'yellow')
    }
    fn = $.proxy(fn, this)
    setTimeout(fn, 1000)
})
  • ES6 Proxy
js 复制代码
// 明星
let star = {
    name: '张xx',
    age: 25,
    phone: '16285838800'
}

// 经纪人
let agent = new Proxy(star, {
    get: function (target, key) {
        if (key === 'phone') {
            // 返回经纪人自己的手机号
            return '18611112222'
        }
        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
            }
        }
    }
})

// test 
console.log(agent.name)
console.log(agent.age)
console.log(agent.phone)
console.log(agent.price)

agent.customPrice = 150000

设计原则验证

  • 代理类和目标类分离,隔离开目标类和使用者
  • 符合开放封闭原则

代理模式vs适配器模式

  • 适配器模式:提供一个不同的接口
  • 代理模式:提供一模一样的接口

代理模式VS装饰器模式

  • 装饰器模式:扩展功能,原有功能不变且可直接使用
  • 代理模式:显示原有功能,但是经过限制或者阉割之后的
相关推荐
触底反弹42 分钟前
🤯 面试被问 AI Workflow 和 Agent 有啥区别?3 张图 + 2 段代码讲清楚!
人工智能·设计模式·面试
杨充21 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充21 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充21 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充21 小时前
2.面向对象的特性
设计模式
杨充21 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充21 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充1 天前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法