标签:JS 设计模式
读书笔记链接:
享元模式
通过划分内部状态与外部状态来减少需要创建对象的数量,共享对象。与其他模式不一样的是,享元模式针对的是性能问题
区分内部状态与外部状态是使用享元模式的关键:
- 内部状态通常是可以被共享的属性,例如性别,岁数,等级之类可以划分出少数几个类别的属性。
- 外部状态就是各不相同的属性,例如大小,面积之类有很多个取值的属性。
- 其实内外状态的区分关键就是看该属性的取值哪个少。选最少哪个作为内部,其他外部。这样就使得共享的对象变到最少。
// 抽出内部属性以创建享元,这里内部属性是sex
// 享元模式也可以使用工厂模式来创建每个享元的单例。严格限定对象数量。
var Modal = function(sex) {
this.sex = sex;
}
Modal.prototype.takePhoto = function(index){
console.log('sex='+this.sex + '; cloth=' + this.clothes[index])
}
// 注意通常要用id++来记录每个享元的外部状态,这里是clothes
Modal.prototype.wear = function(clothes) {this.clothes = clothes};
var maleModal = new Modal('male')
maleModal.wear(['red','green','blue'])
var femaleModal = new Modal('female')
maleModal.wear(['dress','skirt','pants'])
// 这里只使用了两个对象就可以完成任务;其实也可以用cloth来做内部属性,不过有6个值,明显不如sex的两个值
for(var i=0,l=3;i<l;i++){
maleModal.takePhoto(i);
femaleModal.takePhoto(i);
}
另外与一种享元模式有异曲同工之妙的技术是对象池技术,原理是使用缓存记录使用过的对象,调用时优先从缓存调用,调用后就放回缓存。
// objpool
var objectPoolFactory = function(createFn) {
var pool = [];
return {
create: function(){
return obj = pool.length === 0 ? createFn.apply(this, arguments) : pool.shift();
},
recover: function(obj) {
pool.push(obj)
}
}
}
// example
var iframeFactory = objectPoolFactory(function(){
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.onload = function(){
iframe.onload = null; // 防iframe重复加载
iframeFactory.recover(iframe);
}
return iframe;
})
var iframe1 = iframeFactory.create();
iframe1.src = 'http://www.baidu.com';
setTimeout(function(){
var iframe2 = iframeFactory.create(); // iframe1 === iframe2
iframe2.src = 'http://www.qq.com'
}, 5000)
状态模式
使用状态机时,对每一个状态都独立封装成类(对象),各状态类复写同一个抽象方法,使用该方法来执行状态机。
不变:状态总要变化;状态的变换都是通过同一个方法;状态有各自的行为;
变化:状态类的细节;
结果:消除switch语句,不修改原有代码的情况下新增状态
// 状态模式结合有限状态机,开灯例子
var Light = function() {
// 初始状态
// 使用FSM来记录状态对象
this.currState = FSM.off;
this.button = null;
}
Light.prototype.init = function(){
this.button = document.createElement('button');
this.button.innerHTML = 'off';
document.body.append(this.button);
that = this;
this.button.onclick = function(){
that.currState.toggle.call(that);
}
}
// 每个状态都是一个对象,包含自己要维护的属性与一个约定公开的API(这里是toggle)
var FSM = {
off: {
toggle: function(){
console.log('turn off light')
this.currState = FSM.on; // 这里是关键,改变当前状态
}
},
on: {
toggle: function(){
console.log('turn on light')
this.currState = FSM.off; // 这里是关键,改变当前状态
}
}
}
var light = new Light();
light.init();
网友评论