《JS设计模式》读书笔记(六)

标签:JS 设计模式


读书笔记链接:


享元模式

通过划分内部状态与外部状态来减少需要创建对象的数量,共享对象。与其他模式不一样的是,享元模式针对的是性能问题

区分内部状态与外部状态是使用享元模式的关键:

  1. 内部状态通常是可以被共享的属性,例如性别,岁数,等级之类可以划分出少数几个类别的属性。
  2. 外部状态就是各不相同的属性,例如大小,面积之类有很多个取值的属性。
  3. 其实内外状态的区分关键就是看该属性的取值哪个少。选最少哪个作为内部,其他外部。这样就使得共享的对象变到最少。
// 抽出内部属性以创建享元,这里内部属性是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();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,676评论 25 709
  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 2,142评论 1 10
  • 昨天的盘面稍微乐观,挣钱的效应相比于前几天好了很多,然后我们需要看的就是是否有延续性? 如何去看待是否有延续性呢,...
    ViRRo王茜阅读 136评论 0 0
  • 我头脑里总是憧憬着另一种生活,但实际情况却事与愿违。 他只记得那种愤怒本身,不疾不徐却余温犹在。 什么样的母亲不喜...
    够了够了阅读 507评论 0 0
  • 巡游式出差回来,拖着行李走出机场,北京时间23:14,戴晴的消息静静躺在手机里:"哥 落地请开机",刚看完,电话直...
    嗲叔阅读 372评论 0 1