《JS設(shè)計模式》讀書筆記(六)

標簽:JS 設(shè)計模式


讀書筆記鏈接:


享元模式

通過劃分內(nèi)部狀態(tài)與外部狀態(tài)來減少需要創(chuàng)建對象的數(shù)量,共享對象。與其他模式不一樣的是,享元模式針對的是性能問題

區(qū)分內(nèi)部狀態(tài)與外部狀態(tài)是使用享元模式的關(guān)鍵:

  1. 內(nèi)部狀態(tài)通常是可以被共享的屬性,例如性別,歲數(shù),等級之類可以劃分出少數(shù)幾個類別的屬性。
  2. 外部狀態(tài)就是各不相同的屬性,例如大小,面積之類有很多個取值的屬性。
  3. 其實內(nèi)外狀態(tài)的區(qū)分關(guān)鍵就是看該屬性的取值哪個少。選最少哪個作為內(nèi)部,其他外部。這樣就使得共享的對象變到最少。
// 抽出內(nèi)部屬性以創(chuàng)建享元,這里內(nèi)部屬性是sex
// 享元模式也可以使用工廠模式來創(chuàng)建每個享元的單例。嚴格限定對象數(shù)量。
var Modal = function(sex) {
    this.sex = sex;
}
Modal.prototype.takePhoto = function(index){
    console.log('sex='+this.sex + '; cloth=' + this.clothes[index])
}
// 注意通常要用id++來記錄每個享元的外部狀態(tài),這里是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來做內(nèi)部屬性,不過有6個值,明顯不如sex的兩個值
for(var i=0,l=3;i<l;i++){
    maleModal.takePhoto(i);
    femaleModal.takePhoto(i);
}

另外與一種享元模式有異曲同工之妙的技術(shù)是對象池技術(shù),原理是使用緩存記錄使用過的對象,調(diào)用時優(yōu)先從緩存調(diào)用,調(diào)用后就放回緩存。

// 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)


狀態(tài)模式

使用狀態(tài)機時,對每一個狀態(tài)都獨立封裝成類(對象),各狀態(tài)類復寫同一個抽象方法,使用該方法來執(zhí)行狀態(tài)機。

不變:狀態(tài)總要變化;狀態(tài)的變換都是通過同一個方法;狀態(tài)有各自的行為;
變化:狀態(tài)類的細節(jié);

結(jié)果:消除switch語句,不修改原有代碼的情況下新增狀態(tài)

// 狀態(tài)模式結(jié)合有限狀態(tài)機,開燈例子
var Light = function() {
    // 初始狀態(tài)
    // 使用FSM來記錄狀態(tài)對象
    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);
    }
}
// 每個狀態(tài)都是一個對象,包含自己要維護的屬性與一個約定公開的API(這里是toggle)
var FSM = {
    off: {
        toggle: function(){
            console.log('turn off light')
            this.currState = FSM.on;  // 這里是關(guān)鍵,改變當前狀態(tài)
        }
    },
    on: {
        toggle: function(){
            console.log('turn on light')
            this.currState = FSM.off;  // 這里是關(guān)鍵,改變當前狀態(tài)
        }
    }
}

var light = new Light();
light.init();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,109評論 25 709
  • 單例模式 適用場景:可能會在場景中使用到對象,但只有一個實例,加載時并不主動創(chuàng)建,需要時才創(chuàng)建 最常見的單例模式,...
    Obeing閱讀 2,320評論 1 10
  • 昨天的盤面稍微樂觀,掙錢的效應相比于前幾天好了很多,然后我們需要看的就是是否有延續(xù)性? 如何去看待是否有延續(xù)性呢,...
    ViRRo王茜閱讀 153評論 0 0
  • 我頭腦里總是憧憬著另一種生活,但實際情況卻事與愿違。 他只記得那種憤怒本身,不疾不徐卻余溫猶在。 什么樣的母親不喜...
    夠了夠了閱讀 531評論 0 0
  • 巡游式出差回來,拖著行李走出機場,北京時間23:14,戴晴的消息靜靜躺在手機里:"哥 落地請開機",剛看完,電話直...
    嗲叔閱讀 395評論 0 1

友情鏈接更多精彩內(nèi)容