封装事件模块
function Event () {
this.cache = {};
this.onceFlag = {};
}
Event.prototype.on = function (type,handle) {
if (this.cache[type]) {
this.cache[type].push(handle);
} else {
this.cache[type] = [handle];
}
}
Event.prototype.emmit = function (type) {
var args = [].slice.call(arguments,1);
var _this = this;
this.cache[type].forEach(function (item) {
item.apply(_this,args);//没有return ?
if (item.onceFlag) {
_this.remove(type,item);
}
});
}
Event.prototype.remove = function (type, handle) {
this.cache[type] = this.cache[type].filter(function (ele) {
return handle !== ele;
})
}
Event.prototype.empty = function (type) {
this.cache[type] = [];
}
Event.prototype.once = function (type,handle) {
handle.onceFlag = true;
this.add(type,handle);
}
观察者模式
我的状态改变,我就会通知你们,
代理模式
等到你状态改变,我再通知你
咦,发现代理模式和其他模式有个不一样的地方,
代理模式是有监听的,
不是目标对象状态改变后通知我,
而是我不停的监听目标对象的状态.
案例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewprot" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>dddd</title>
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
// 封装事件模块
function Event () {
this.cache = {};
this.onceFlag = {};
}
Event.prototype.on = function (type,handle) {
if (this.cache[type]) {
this.cache[type].push(handle);
} else {
this.cache[type] = [handle];
}
}
Event.prototype.emmit = function (type) {
var args = [].slice.call(arguments,1);
var _this = this;
this.cache[type].forEach(function (item) {
item.apply(_this,args);
if (item.onceFlag) {
_this.remove(type,item);
}
});
}
Event.prototype.remove = function (type, handle) {
this.cache[type].filter(function (ele) {
return handle !== ele;
})
}
Event.prototype.empty = function (type) {
this.cache[type] = [];
}
Event.prototype.once = function (type,handle) {
handle.onceFlag = true;
this.add(type,handle);
}
// 继承事件模块
PlaneFactory.prototype = new Event();
// 装饰者模式
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) {
//
if(typeof this.decorators[decorator] == "function")
this.decorate_list.push(this.decorators[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);
oAp.on('over',function () {
this.die();
})
oSp.emmit('over');
// 由于把事件模块绑定在了顶端抽象工厂上,所以事件可被所有实例所触发.
// 解决办法是 把事件模块让每个实例 继承, 这样互不干扰
// 又或者,增加一个维度,除了 type, 再加一个标识,用来标识 不同实例?
</script>
</body>
</html>