享元模式

目標

通過儘量減少共享對象的數量,運用共享技術來有效支持大量細粒度的對象。

要點

  • 享元模式是一種用時間換空間的性能優化模式。
  • 享元模式要求將對象的屬性劃分為內部狀態和外部狀態,所有內部狀態相同的對象都指定為同一個共享的對象,外部狀態在必要時被傳入共享對象來組裝成一個完整的對象。
  • 劃分內部狀態和外部狀態的關鍵在於:內部狀態存儲於對象內部;內部狀態獨立於具體的場景,通常不會改變。
  • 有多少種內部狀態的組合,系統中便最多存在多少個共享對象。
  • 享元模式的適用場景:程序中使用了大量的對象;使用的大量對象造成了很大的內開銷;對象的大多數狀態可以變為外部狀態;剝離出對象的外部狀態之後,可以用相對較少的共享對象取代大量對象。
  • 沒有內部狀態的享元模式只需要唯一的一個共享對象,生產共享對象的工廠實際上變成了一個單例工廠。但因為有剝離外部狀態的過程,所以它還是屬於享元模式。
  • 對象池:另一種和享元模式相似的性能優化方案,但沒有分離內部狀態和外部狀態的過程。

核心代碼

var Upload = function(uploadType) {
    this.uploadType = uploadType;
};

var UploadFactory = (function() {
    var createdFlyWeightObjs = {};
    return {
        create: function(uploadType) {
            if (createdFlyWeightObjs[uploadType]) {
                return createdFlyWeightObjs[uploadType];
            } else {
                return createdFlyWeightObjs[uploadType] = new Upload(uploadType);
            }
        }
    };
})();

var uploadManager = (function() {
    var uploadDatabase = {};
    return {
        add: function(id, uploadType, otherParams) {
            var flyWeightObj = UploadFactory.create(uploadType);
            // 結合外部狀態進行操作
            // ...
            uploadDatabase[id] = {
                // 記錄 id 號的對象對應的外部狀態
                // ...
            };
            return flyWeightObj;
        },
        setExternalState: function(id, flyWeightObj) {
            var uploadData = uploadDatabase[id];
            for (var i in uploadData) {
                flyWeightObj[i] = uploadData[i];
            }
        }
    };  
})();
\\ 通用對象池的實現
var objectPoolFactory = function(createObjFn) {
    var objectPool = [];
    return {
        create: function() {
            var obj = objectPool.length ? objectPool.shift() : createObjFn.apply(this, arguments);
            return obj;
        },
        recover: function(obj) {
            objectPool.push(obj);
        }
    };
};

var iframeFactory = objectPoolFactory(function() {
    var iframe = document.createElement('iframe');
    // ...
    iframe.onload = function() {
        iframe.onload = null;
        iframeFactory.recover(iframe);    // iframe 加載完成之後回收
    };
    return iframe;
});

var iframe1 = iframeFactory.create();
iframe1.src = 'http://baidu.com';

setTimeout(function() {
    var iframe2 = iframeFactory().create();
    iframe2.src = 'http://qq.com';
}, 30000);

你可能感兴趣的:(享元模式)