定义: 在不改变元对象的基础上,通过对其进行包装拓展(添加属性方法)
装饰着(decorator) 模式能够在不改变对象自身的基础上,
在程序运行期间给对象动态的添加职责.
与继承相比,装饰着是一种更轻便,更灵活的做法.
当脚本运行时,
如果在子类中增加行为会影响原有类所有的实例,(指的应该是工厂模式?)
而装饰者,能给不同对象各自添加新行为和属性.
先记录一下,呆会再移动到别的位置.
是这样的,
无论是传参还是调用方法,
我发现有两种不同的形式,
第一种是,我传一个值,也就是所谓的值.
第二种是,我传一个索引,存在一个库,所有的值按照某种规则,
放置在库中,根据这个索引,在库中找到相应的值,
这个值可能是数据,也有可能是函数.
策略模式,工厂模式,以及今天的装饰者模式都给了我强烈的上面的印象.
也就是说,要形成一个库,这个库可能是一个数组,也有可能是一个对象,
这样做的好处是显而易见的,
那就是整齐,有规律,有结构
导致复用性,扩展性变得很强.
所以我们尽可能要有这种思维.
无论是函数,还是一些值,都尽量弄一些库区储存.
从另外一个角度上来讲.
也许所有处理事件时,产生的数据和方法,都有必要以某种形式储存下来?
无脑储存明显会感觉占用空间,
但也许是提升效率的关键?
当然以上都是一种感觉, 实际上我可能还无法识别什么是该这样处理的情况.
更谈不上什么操作.
另一个有感是,
函数的执行问题.
通过用一个函数定义形态包裹函数执行形态,
我们可以实现执行时机的选择,
我们也可以放进某个数组里,来实现同时执行?
<script type="text/javascript">
//抽象工厂模式
function PlaneFactory () {
// 资源池也可以设定在子类上,让每个实例拥有不同的资源池?
this.decorate_list = [];
}
// 集合所有装饰方法
PlaneFactory.prototype.decorators = {
eatOneLife: function (obj) {// 这就明显不是继承了,而是直接在对象上增删改查了.
obj.blood += 100;
},
eatTwoLife: function (obj) {
obj.blood += 200;
}
}
// 搜集对某对象的装饰描述
PlaneFactory.prototype.decorate = function (decorator) {
//
this.decorate_list.push(decorator);
}
// 更新, 让装饰方法作用在该对象的身上
PlaneFactory.prototype.update = function () {
for (var i = 0; i < this.decorate_list.length;i++) {
this.decorators[ this.decorate_list[i] ] && this.decorators[ this.decorate_list[i] ](this);
}
}
PlaneFactory.prototype.empty = function () {
// 清空
this.decorate_list = [];
}
PlaneFactory.prototype.remove = function (type) {
// 删除
this.decorate_list = this.decorate_list.filter(function (ele) {
return type !== ele
})
}
//子类工厂都可以使用的公共方法.
PlaneFactory.prototype.touch = function () {
this.blood -= 50;
console.log(this.blood);
if (this.blood <= 0) {
this.die();
}
PlaneFactory.prototype.die = function () {
alert('boomb');
}
}
// 创建对象的接口 // 这个接口定义在函数上,类似jq的工具方法.
// 如果该接口定义在原型上, 则必须实例化之后才能调用, 跟现实场景模拟不符.
PlaneFactory.create = function (type) {
// 判定是否存在该类型的子类工厂.
if (PlaneFactory.prototype[type] == undefined) {
throw 'no this constructor'
}
//实现继承 子工厂继承PlaneFactory
if (PlaneFactory.prototype[type].prototype.__proto__ !== PlaneFactory.prototype) {// 这个条件时判断有没有完成继承
// 问题? 重复继承会怎么样? 继承虽然没什么问题, 但 子工厂的 原型就会被刷新, 有可能会把在外面定义在在该原型的数据抹掉.
PlaneFactory.prototype[type].prototype = new PlaneFactory();
}
// 创建对象
var arg = [].slice.call(arguments,1);
var newPlane = new PlaneFactory.prototype[type](...arg);
// new 的时候 不好用call | apply 因为会改变this指向, 而new 是为了生成新的this 应该是有冲突..
return newPlane;
}
// 真正定义子类工厂
PlaneFactory.prototype.SmallPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 100;
this.height = 100;
this.name = 'smallPlane';
this.blood = 100;
}
PlaneFactory.prototype.BigPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 150;
this.height = 200;
this.name = 'bigPlane';
this.blood = 200;
}
PlaneFactory.prototype.AttackPlane = function (x, y) {
this.x = x;
this.y = y;
this.width = 120;
this.height = 100;
this.name = 'attackPlane';
this.blood = 100;
this.attack = function () {
console.log('biu');
}
}
var oAp = PlaneFactory.create('AttackPlane',10,20);
var oSp = PlaneFactory.create('SmallPlane',20,30);
var oBp = PlaneFactory.create('BigPlane',40,50);
// 装饰者模式
oAp.decorate('eatOneLife');
oAp.decorate('eatTwoLife');
oAp.remove('eatOneLife');// remove 只有在 update()执行前有效果.
oAp.update();
console.log(oAp);
从结构上看,
装饰者模式和策略模式有很相似的地方.
都是在原型上有个存放核心函数的对象.
strategies 对应 decorators
还有可以扩展.
extend 对应 这里似乎没写,不过应该可以完全差不多.
还有有个资源池?
cache 对应 decorate_list //
不过根据需求,这个decorate_list 可以定义在抽象工厂类上,也可以定义子类上.
添加要执行的东西.
add 对应 decorate
不过两者有很大的不同,相比之下,
add接收了更多的函数,存放的也不是简单的 type
而是根据strategies和传入的参数(包括dom)相结合的执行函数,放进一个函数中,
在放入cache中
执行列表
start 对应的是 update
装饰者模式,
多了个remove 和 empty 都是操作decorate_list的
而在策略模式的案例中,
直接就是 把 cache = [] 也就是直接进行了清空操作.
这种结构,就是某种隐含的套路