天天看點

享元模式

享元模式

Flyweight Pattern

主要用于減少建立對象的數量,以減少記憶體占用和提高性能,其提供了減少對象數量進而改善應用所需的對象結構的方式,享元模式嘗試重用現有的同類對象,如果未找到比對的對象,則建立新對象。享元模式運用共享技術有效地支援大量細粒度對象的複用,系統隻使用少量的對象,而這些對象都很相似,狀态變化很小,可以實作對象的多次複用,由于享元模式要求能夠共享的對象必須是細粒度對象,是以它又稱為輕量級模式,其是一種對象結構型模式。

描述

面向對象技術可以很好地解決一些靈活性或可擴充性問題,但在很多情況下需要在系統中增加類和對象的個數,當對象數量太多時,将導緻運作代價過高,帶來性能下降等問題。享元模式正是為解決這一類問題而誕生的,享元模式通過共享技術實作相同或相似對象的重用。在享元模式中可以共享的相同内容稱為内部狀态

IntrinsicState

,而那些需要外部環境來設定的不能共享的内容稱為外部狀态

Extrinsic State

,由于區分了内部狀态和外部狀态,是以可以通過設定不同的外部狀态使得相同的對象可以具有一些不同的特征,而相同的内部狀态是可以共享的。在享元模式中通常會出現工廠模式,需要建立一個享元工廠來負責維護一個享元池

Flyweight Pool

用于存儲具有相同内部狀态的享元對象。在享元模式中共享的是享元對象的内部狀态,外部狀态需要通過環境來設定。在實際使用中,能夠共享的内部狀态是有限的,是以享元對象一般都設計為較小的對象,它所包含的内部狀态較少,這種對象也稱為細粒度對象,享元模式的目的就是使用共享技術來實作大量細粒度對象的複用。

模式結構

  • Flyweight

    : 抽象享元類。
  • ConcreteFlyweight

    : 具體享元類。
  • UnsharedConcreteFlyweight

    : 非共享具體享元類。
  • FlyweightFactory

    : 享元工廠類。

優點

  • 享元模式的優點在于它可以極大減少記憶體中對象的數量,使得相同對象或相似對象在記憶體中隻儲存一份。
  • 享元模式的外部狀态相對獨立,而且不會影響其内部狀态,進而使得享元對象可以在不同的環境中被共享。

缺點

  • 享元模式使得系統更加複雜,需要分離出内部狀态和外部狀态,這使得程式的邏輯複雜化。
  • 為了使對象可以共享,享元模式需要将享元對象的狀态外部化,而讀取外部狀态使得運作時間變長。

适用環境

  • 一個系統有大量相同或者相似的對象,由于這類對象的大量使用,造成記憶體的大量耗費。
  • 對象的大部分狀态都可以外部化,可以将這些外部狀态傳入對象中。
  • 使用享元模式需要維護一個存儲享元對象的享元池,而這需要耗費資源,是以應當在多次重複使用享元對象時才值得使用享元模式。

實作

class Tea { // 茶産品類 執行個體為被共用的對象
    constructor(preference){
        this.preference = preference;
    }
}

class TeaMaker { // 作為茶工廠以建立茶的執行個體 即享元工廠來負責維護一個享元池
    constructor(){
        this.availableTea = {};
    }

    make(preference) {
        this.availableTea[preference] = this.availableTea[preference] || (new Tea());
        return this.availableTea[preference];
    }
}

(function TeaShop(){
    const shop = new TeaMaker();
    var lessSugar1 = shop.make("less sugar");
    var moreMilk1 = shop.make("more milk");
    var withoutSugar1 = shop.make("without sugar");
    var lessSugar2 = shop.make("less sugar");
    var moreMilk2 = shop.make("more milk");
    var withoutSugar3 = shop.make("without sugar");
    console.log(lessSugar1 === lessSugar2); // true
    console.log(moreMilk1 === moreMilk2); // true
    console.log(withoutSugar1 === withoutSugar3); // true
})();
           

每日一題

https://github.com/WindrunnerMax/EveryDay
           

參考

https://www.runoob.com/design-pattern/flyweight-pattern.html
https://github.com/sohamkamani/javascript-design-patterns-for-humans#-flyweight
https://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/flyweight.html
           
上一篇: SVG基礎
下一篇: 組合模式