實現物件的複用——享元模式(一)

Liuwei-Sunny發表於2012-06-15

        當前我們們國家正在大力倡導構建和諧社會,其中一個很重要的組成部分就是建設資源節約型社會,“浪費可恥,節儉光榮”。在軟體系統中,有時候也會存在資源浪費的情況,例如在計算機記憶體中儲存了多個完全相同或者非常相似的物件,如果這些物件的數量太多將導致系統執行代價過高,記憶體屬於計算機的“稀缺資源”,不應該用來“隨便浪費”,那麼是否存在一種技術可以用於節約記憶體使用空間,實現對這些相同或者相似物件的共享訪問呢?答案是肯定,這種技術就是我們本章將要學習的享元模式。

14.1 圍棋棋子的設計

      Sunny軟體公司欲開發一個圍棋軟體,其介面效果如圖14-1所示:

14-1 圍棋軟體介面效果圖

      Sunny軟體公司開發人員通過對圍棋軟體進行分析,發現在圍棋棋盤中包含大量的黑子和白子,它們的形狀、大小都一模一樣,只是出現的位置不同而已。如果將每一個棋子都作為一個獨立的物件儲存在記憶體中,將導致該圍棋軟體在執行時所需記憶體空間較大,如何降低執行代價、提高系統效能是Sunny公司開發人員需要解決的一個問題為了解決這個問題,Sunny公司開發人員決定使用享元模式來設計該圍棋軟體的棋子物件,那麼享元模式是如何實現節約記憶體進而提高系統效能的呢?彆著急,下面讓我們正式進入享元模式的學習。

14.2 享元模式概述

      當一個軟體系統在執行時產生的物件數量太多,將導致執行代價過高,帶來系統效能下降等問題。例如在一個文字字串中存在很多重複的字元,如果每一個字元都用一個單獨的物件來表示,將會佔用較多的記憶體空間,那麼我們如何去避免系統中出現大量相同或相似的物件,同時又不影響客戶端程式通過物件導向的方式對這些物件進行操作?享元模式正為解決這一類問題而誕生。享元模式通過共享技術實現相同或相似物件的重用,在邏輯上每一個出現的字元都有一個物件與之對應,然而在物理上它們卻共享同一個享元物件這個物件可以出現在一個字串的不同地方,相同的字元物件都指向同一個例項,在享元模式中,儲存這些共享例項物件的地方稱為享元池(Flyweight Pool)我們可以針對每一個不同的字元建立一個享元物件,將其放在享元池中,需要時再從享元池取出。如圖14-2所示:

14-2 字元享元物件示意圖

      享元模式以共享的方式高效地支援大量細粒度物件的重用,享元物件能做到共享的關鍵是區分了內部狀態(Intrinsic State)外部狀態(Extrinsic State)。下面將對享元的內部狀態和外部狀態進行簡單的介紹:

      (1)  內部狀態是儲存在享元物件內部並且不會隨環境改變而改變的狀態,內部狀態可以共享如字元的內容,不會隨外部環境的變化而變化,無論在任何環境下字元“a”始終是“a”,都不會變成“b”。

      (2)  外部狀態是隨環境改變而改變的、不可以共享的狀態享元物件的外部狀態通常由客戶端儲存,並在享元物件被建立之後,需要使用的時候再傳入到享元物件內部。一個外部狀態與另一個外部狀態之間是相互獨立的。如字元的顏色,可以在不同的地方有不同的顏色,例如有的“a”是紅色的,有的“a”是綠色的,字元的大小也是如此,有的“a”是五號字,有的“a”是四號字。而且字元的顏色和大小是兩個獨立的外部狀態,它們可以獨立變化,相互之間沒有影響,客戶端可以在使用時將外部狀態注入享元物件中。

      正因為區分了內部狀態和外部狀態,我們可以將具有相同內部狀態的物件儲存在享元池中,享元池中的物件是可以實現共享的,需要的時候就將物件從享元池中取出,實現物件的複用。通過向取出的物件注入不同的外部狀態,可以得到一系列相似的物件,而這些物件在記憶體中實際上只儲存一份。

      享元模式定義如下:

享元模式(Flyweight Pattern):運用共享技術有效地支援大量細粒度物件的複用。系統只使用少量的物件,而這些物件都很相似,狀態變化很小,可以實現物件的多次複用。由於享元模式要求能夠共享的物件必須是細粒度物件,因此它又稱為輕量級模式,它是一種物件結構型模式。

【作者:劉偉  http://blog.csdn.net/lovelion

相關文章