js常用设计模式1-单例模式
js常用设计模式2-策略模式
js常用设计模式3-代理模式
js常用设计模式4-发布-订阅模式
js常用设计模式5-命令模式
js常用设计模式6-组合模式
js常用设计模式7-享元模式
js常用设计模式8-职责链模式
js常用设计模式9-中介者模式
js常用设计模式10-装饰者模式
js常用设计模式11-状态模式
能动态的给对象增加职责的方式称为装饰者模式。
装饰者模式能够在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责。跟继承相比,装饰者模式灵活很多,“即用即付”,有点热插拔那味了。
1,装饰者模式实现飞机大战
现在我们有一个飞机,初始1级的时候可以发射子弹,2级之后可以发射导弹,3级的时候可以发射原子弹:
//一个简单地打飞机
var plane = {
fire: function () {
console.log('发射普通子弹')
}
}
var missleDecorator = function () {
console.log('发射导弹')
}
var atomDecorator = function () {
console.log('发射原子弹')
}
var fire1 = plane.fire
plane.fire = function () {
fire1()
missleDecorator()
}
var fire2 = plane.fire
plane.fire = function () {
fire2()
atomDecorator()
}
plane.fire()
// 分别输出: 发射普通子弹 发射导弹 发射原子弹
2,用AOP装饰函数
使用AOP也就是要在函数执行的before和after做一些处理,那么我们就实现一下Function.prototype.before和Function.prototype.after:
//AOP装饰函数
Function.prototype.before = function (beforeFn) {
var _self = this
//返回原函数和新函数的’代理‘函数
return function () {
//保证this不被劫持
beforeFn.apply(this, arguments)
return _self.apply(this, arguments)
}
}
Function.prototype.after = function (afterFn) {
var _self = this
return function () {
var result = _self.apply(this, arguments)
afterFn.apply(this, arguments)
return result
}
}
可以在下面的例子中体会_self的用处
3,试一试before的威力
Function.prototype.before = function (beforeFn) {
var _self = this
//返回原函数和新函数的’代理‘函数
return function () {
//保证this不被劫持
beforeFn.apply(this, arguments)
return _self.apply(this, arguments)
}
}
在这个例子中,_self指的是document.getElementById.before这个函数上面,bofore的调用者,实际上是getElementById而不是document,因为getElementById是最后一层的调用者,当document.getElementById = document.getElementById.before()之后,document.getElementById指向的就是before返回的函数,其中的this就是getElementById函数的调用者,也就是document。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<div id="button">11</div>
</head>
<body>
<script>
/**
* 装饰者模式和代理模式的区别
* 装饰者可以添加很多不同的东西,有点按需加载的意思
* 代理只是专门处理一件事,需求一开始就是明确的
*/
Function.prototype.before = function (beforeFn) {
var _self = this
//返回原函数和新函数的’代理‘函数
return function () {
//保证this不被劫持
beforeFn.apply(this, arguments)
return _self.apply(this, arguments)
}
}
Function.prototype.after = function (afterFn) {
var _self = this
return function () {
var result = _self.apply(this, arguments)
afterFn.apply(this, arguments)
return result
}
}
document.getElementById = document.getElementById.before(function () {
console.log('before')
})
var button = document.getElementById('button')
window.alert = window.alert.before(function () {
console.log(1)
})
alert(2)
</script>
</body>
</html>