装饰者模式
装饰者模式的作用就是为对象动态加入行为
装饰者模式经常会形成一条长长的装饰链
// 装饰者模式
var Plane = function() {};
Plane.prototype.fire = function() {
console.log("发射普通子弹");
};
var daodan = function(plane) {
this.plane = plane;
};
daodan.prototype.fire = function() {
this.plane.fire();
console.log("发射导弹");
};
var automatic = function(plane) {
this.plane = plane;
};
automatic.prototype.fire = function() {
this.plane.fire();
console.log("发射原子弹");
};
var plane = new Plane(),
ss = new daodan(plane),
sss = new automatic(ss);
sss.fire();
// javascript 实现装饰者模式
var plane = {
fire: function() {
console.log("发射普通子弹");
}
};
var fire1 = plane.fire;
var daodan = {
fire: function() {
fire1();
console.log("发射导弹");
}
};
var fire2 = daodan.fire;
var automatic = {
fire: function() {
fire2();
console.log("发射原子弹");
}
};
automatic.fire();
```js
这种给对象动态增加职责的方式,并没有真正地改动对象自身,而是将对象放入另一个对象之中,这些对象以一条链的方式进行引用,形成一个聚合对象。
这些对象都拥有相同的接口(fire方法),当请求达到链中的某个对象时,这个对象会执行自身的操作,随后把请求转发给链中的 下一个对象
```js
// AOP 实现装饰者模式
Function.prototype.before = function(beforeFn) {
var self = this;
return function() {
beforeFn.apply(this, arguments);
return self.apply(this, arguments);
};
};
Function.prototype.after = function(afterFn) {
var self = this;
return function() {
var ret = self.apply(this, arguments);
afterFn.apply(this, arguments);
return ret;
};
};
(window.onload || function() {})
.before(function() {
console.log(1);
})
.before(function() {
console.log(2);
})
.before(function() {
console.log(3);
})();
// 不污染原型链的做法
var before = function(fn, beforefn) {
return function() {
beforefn.apply(this, arguments);
return fn.apply(this, arguments);
};
};
var a = before(
function() {
console.log(4);
},
function() {
console.log(5);
}
);
a = before(a, function() {
console.log(6);
});
a = a();
// 装饰者模式会动态改变arguments
Function.prototype.before = function(beforeFn) {
var self = this;
return function() {
beforeFn.apply(this, arguments);
return self.apply(this, arguments);
};
};
var func = function(param) {
console.log(param);
};
func = func.before(function(param) {
param.b = "b";
});
func({ a: "a" });
// 装饰者模式应用在表单提交
Function.prototype.before = function(beforeFn) {
var self = this;
return function() {
if (!beforeFn.apply(this, arguments)) {
return;
}
return self.apply(this, arguments);
};
};
function submit(name) {
console.log("submit success, name: ", name);
}
function validate(name) {
if (!name) {
console.log("name is not arrowed empty, not arrowed to submit");
return false;
}
return true;
}
function init() {
var div = document.createElement("div");
div.innerHTML =
'<p><label>name</label> <input id="username" placeholder="please input your name"/></p><p><button id="submit">submit</button></p>';
document.body.appendChild(div);
var sub = document.getElementById("submit");
var test = submit.before(validate);
sub.onclick = function() {
var value = document.getElementById("username").value;
test(value);
};
}
init();
用AOP实现职责链既简单又巧妙,但这种把函数叠在一起的方式,同时也叠加了函数的作用域,如果链条太长的话,也会对性能有影响。