装饰者(decorator)模式能够在不改变对象自身的基础上,在程序运行期间给对像动态的添加职责。与继承相比,装饰者是一种更轻便灵活的做法。可以当脚本运行时,在子类中增加行为会影响原有类所有的实例,而装饰者却不然。取而代之的是它能给不同对象各自添加新行为
实现: 构造函数需要一个装饰资源池,提供相应的装饰方法,提供添加装饰方法的方法。
场景:工厂方法模式生产不同类型的飞机;装饰者模式增加不同的血量。
代码中用到工厂方法模式 工厂方法模式实现
function PlaneFactory() {
this.decorator_list = [];//装饰资源池
}
PlaneFactory.create = function (type) {
let newPlane;
if (!PlaneFactory.prototype[type]) {
throw '没有此类型';
}
if (PlaneFactory.prototype[type].prototype.__proto__ != PlaneFactory.prototype) {
PlaneFactory.prototype[type].prototype = new PlaneFactory();
}
const arg = [].slice.call(arguments, 1);
newPlane = new PlaneFactory.prototype[type](...arg);
return newPlane;
}
//已经有的装饰方法
PlaneFactory.prototype.decorators = {
'eatOneLife': function (_this) {
_this.boold += 100;
},
'eatTwoLife': function (_this) {
_this.boold += 200;
}
}
//添加装饰方法
PlaneFactory.prototype.decorator = function (type) {
if (this.decorator_list.indexOf(type) < 0) {
this.decorator_list.push(type);
} else {
throw '已有此装饰方法';
}
}
//执行装饰方法
PlaneFactory.prototype.upDate = function () {
for (let i = 0; i < this.decorator_list.length; i++) {
this.decorators[this.decorator_list[i]] && this.decorators[this.decorator_list[i]](this);
}
}
//清空装饰资源池
PlaneFactory.prototype.empty = function () {
this.decorator_list = [];
}
//移除某一装饰方法
PlaneFactory.prototype.remove = function (type) {
this.decorator_list = this.decorator_list.filter(ele => {
return ele != type;
})
}
PlaneFactory.prototype.die = function () {
console.log('boom');
}
PlaneFactory.prototype.touch = function () {
this.boold -= 100;
if (this.boold == 0) {
console.log('die')
}
}
PlaneFactory.prototype.smallPlane = function (x, y) {
this.x = x;
this.y = y;
this.boold = 100;
this.name = 'smallPlane';
}
PlaneFactory.prototype.bigPlane = function (x, y) {
this.x = x;
this.y = y;
this.boold = 200;
this.name = 'bigPlane';
}
//工厂方法模式创建对象
const small = PlaneFactory.create('smallPlane', 10, 20);
const big = PlaneFactory.create('bigPlane', 20, 30);
small.decorator('eatOneLife');
small.upDate();
consoel.log(small);//小飞机血量增加
big.decorator('eatTwoLife');
big.upDate();
console.log(big);//大飞机血量增加