爲方便讀者,本文已添加至索引:html
Flyweight(享元)模式運用共享技術,能夠有效地支持大量細粒度的對象。今天咱們會去參觀小霍比特人們的釀酒工坊……等等,不是享元模式嗎?那好吧,咱們推遲到示例一節中前往參觀。設計模式
咱們在作面向對象的設計時,經常但願能用對象來表示某個具體的事物,好比一個紅富士蘋果或是一輛凱迪拉克跑車。當咱們把這種思惟帶到一些程序設計任務中去時,可能就會遭遇處處理存儲開銷和程序自己靈活性的一個平衡問題。例如,咱們在設計一個遊戲,主人公走到一片蘋果園,看見滿滿一屏幕的蘋果。更高級的是,每一個蘋果都能與主人公進行交互,不管是近處的(直接摘下來吃了),仍是遠處的(我拿石頭扔,我扔)。若是每一個蘋果都用不一樣的對象來表示,的確能夠極大提升這個遊戲的視覺效果,由於這樣咱們能夠給每一個蘋果定製徹底不一樣的外觀(這屬於蘋果的內部因素),俗話說,世界上沒有兩個相同的蘋果(...葉子如是,蘋果應該也不差)。可是,若是蘋果園裏,有成千上萬個蘋果呢?這能形成巨大的存儲開銷。事實上,玩遊戲的時候,咱們纔不會太在乎這個蘋果長什麼樣,除非是兩個徹底不一樣種類的蘋果。因此,若是能只存儲一個蘋果的外觀,渲染成千上萬個(存在距離、光照等外部因素),咱們也不會以爲哪裏不舒服,仍是會朝那些蘋果扔石頭。這隻被共享的蘋果,便引出了咱們的Flyweight模式。先來看看它的一些要點。數組
還記得這羣可愛的小霍比特人們嗎?(若是不瞭解他們,請見AbstractFactory筆記)喜歡開Party的他們,天然得有喝不完的好酒相伴。時の魔導士早先的時候曾給他們留下過一座釀酒工坊WineFactory。這座工坊能夠生產各式基酒,譬如威士忌Whiskey,朗姆酒Rum,葡萄酒Wine等等。小霍比特人們,能夠根據本身的口味,添加一些果汁、牛奶、咖啡、糖等等輔料,從而調製出一杯美味的雞尾酒Cocktail。學習
在這個魔法世界裏,咱們忽略每種基酒的釀造工藝上的不一樣,而假定它們的內部狀態是相同的(都含有酒精),區分它們的僅僅是口感的類型不一樣。所以,咱們能夠將基酒視做爲一類ConcreteFlyweight,基酒類BaseWine繼承自Drink:spa
1 class Drink { 2 public: 3 virtual ~Drink(); 4 5 virtual void mix(Ingredient&); // can mix with other ingredients. 6 virtual void drink(); 7 protected: 8 Drink(); 9 } 10 11 class BaseWine : public Drink { 12 public: 13 BaseWine(int type); 14 15 virtual void mix(Ingredient&); 16 private: 17 int _type; 18 }
當小霍比特人拜訪釀酒工坊WineFactory,想要來一杯的時候。工坊會先看看他要的這種基酒是否已經釀造好了,有的話,直接取一份給他;不然,就釀造出取之不盡的這種基酒。設計
1 #define WHISKEY 1 2 #define RUM 2 3 #define VODKA 3 4 #define GIN 4 5 // ... other definitions ... 6 #define MAX_TYPES 10 7 8 class WineFactory { 9 public: 10 WineFactory(); 11 virtual ~WineFactory(); 12 virtual BaseWine* createWine(int type); 13 14 private: 15 BaseWine* _wine[MAX_TYPES]; 16 } 17 18 // Initialize the wine pool. 19 WineFactory::WineFactory() { 20 for (int i = 0; i < MAX_TYPES; ++i) { 21 _wine[i] = 0; 22 } 23 } 24 25 // Check the pool before create wine. 26 BaseWine* WineFactory::createWine(int type) { 27 if (!_wine[type]) { 28 _wine[type] = new BaseWine(type); 29 } 30 31 return _wine[type]; 32 }
咱們看到,_wine數組包含一些指針,指向以基酒品種爲索引的BaseWine,createWine方法首先會查找這個數組,若是數組中存在這種BaseWine,則能夠直接返回,不然,new一個新的。這樣作的一個好處是,酒的種類每每是有限且很少的,可是咱們能夠卻能夠共享這些種類並用在不少不少場景下。這個簡單例子的UML圖以下:指針
Flyweight主要針對存儲節約提出瞭解決方案,它所節約的部分主要由如下幾個因素決定:code
共享的Flyweight越多,存儲節約也就越多。節約量隨着共享狀態的增多而增大。當對象使用大量的內部及外部狀態,而且外部狀態是計算出來的而非存儲的時候,節約量將達到最大。因此,能夠用兩種方法來節約存儲:用共享減小內部狀態的消耗,用計算時間換取對外部狀態的存儲。htm
在使用Flyweight模式時,咱們須要注意如下幾點:對象
今天的筆記就到這裏了,歡迎你們批評指正!若是以爲能夠的話,好文推薦一下,我會很是感謝的!