JavaScript design pattern-proxy pattern

1. Agency model

1.1 Introduction to Proxy Mode

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

1.2 Proxy model class diagram

  • 传统 UML 类图
    Insert picture description here
  • 简化后的 UML 类图
    Insert picture description here

1.3 Demonstration of Proxy Mode

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()

1.4 Proxy mode scenario

1.4.1 Web event proxy
<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>
1.4.2 jQuery 中 $.proxy
$('#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)
});
1.4.3 Proxy in ES6
// 明星
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 = 90000
console.log('agent.customPrice', agent.customPrice);

1.5 Verification of the design principles of the agency model

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

1.6 Proxy Mode VS Adapter Mode

  • 适配器模式
    • Provide one 不同的接口(such as a different version of the plug)
    • The user wants to use the target class
    • but目标类老旧或格式不一样,不能用
    • Need to add a third-party adapter to configure for format conversion
    • So provide a different interface
  • 代理模式
    • provide一模一样的接口
    • user无权使用目标类
    • But need to use the permissions of the target class
    • Need a proxy, the same interface as the target class

1.7 Proxy Mode VS Decorator Mode

  • 装饰器模式
    • 扩展功能,原有功能不变且可直接使用
    • 扩展功能与原有功能并不冲突
  • 代理模式
    • 显示原有功能,但是经过限制或者阉割之后的

Guess you like

Origin blog.csdn.net/qq_43645678/article/details/114543029