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

作者: philoZhe | 来源:发表于2016-11-23 23:53 被阅读71次

    标签: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();
    

    相关文章

      网友评论

        本文标题:《JS设计模式》读书笔记(六)

        本文链接:https://www.haomeiwen.com/subject/jqxbpttx.html