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

Liuwei-Sunny發表於2012-06-15

14.5 單純享元模式和複合享元模式

       標準的享元模式結構圖中既包含可以共享的具體享元類,也包含不可以共享的非共享具體享元類。但是在實際使用過程中,我們有時候會用到兩種特殊的享元模式:單純享元模式和複合享元模式,下面將對這兩種特殊的享元模式進行簡單的介紹:

       1.單純享元模式

       在單純享元模式中,所有的具體享元類都是可以共享的,不存在非共享具體享元類。單純享元模式的結構如圖14-6所示:

14-6  單純享元模式結構圖

       2.複合享元模式

       將一些單純享元物件使用組合模式加以組合,還可以形成複合享元物件,這樣的複合享元物件本身不能共享,但是它們可以分解成單純享元物件,而後者則可以共享。複合享元模式的結構如圖14-7所示:

14-7  複合享元模式結構圖

       通過複合享元模式,可以確保複合享元類CompositeConcreteFlyweight中所包含的每個單純享元類ConcreteFlyweight都具有相同的外部狀態,而這些單純享元的內部狀態往往可以不同。如果希望為多個內部狀態不同的享元物件設定相同的外部狀態,可以考慮使用複合享元模式。

14.6 關於享元模式的幾點補充

       1.與其他模式的聯用

       享元模式通常需要和其他模式一起聯用,幾種常見的聯用方式如下:

       (1)在享元模式的享元工廠類中通常提供一個靜態的工廠方法用於返回享元物件,使用簡單工廠模式來生成享元物件。

       (2)在一個系統中,通常只有唯一一個享元工廠,因此可以使用單例模式進行享元工廠類的設計。

       (3)享元模式可以結合組合模式形成複合享元模式,統一對多個享元物件設定外部狀態。

       2.享元模式與String

       JDK類庫中的String類使用了享元模式,我們通過如下程式碼來加以說明:

class Demo {

       public  static void main(String args[]) {

              String  str1 = "abcd";

              String  str2 = "abcd";

              String  str3 = "ab" + "cd";

              String  str4 = "ab";

              str4  += "cd";

             

              System.out.println(str1  == str2);

              System.out.println(str1  == str3);

              System.out.println(str1  == str4);

             

              str2  += "e";

              System.out.println(str1  == str2);

       }

}

       在Java語言中,如果每次執行類似String str1="abcd"的操作時都建立一個新的字串物件將導致記憶體開銷很大,因此如果第一次建立了內容為"abcd"的字串物件str1,下一次再建立內容相同的字串物件str2時會將它的引用指向"abcd",不會重新分配記憶體空間,從而實現了"abcd"在記憶體中的共享。上述程式碼輸出結果如下:

true

true

false

false

       可以看出,前兩個輸出語句均為true,說明str1str2str3在記憶體中引用了相同的物件;如果有一個字串str4,其初值為"ab",再對它進行操作str4 += "cd",此時雖然str4的內容與str1相同,但是由於str4的初始值不同,在建立str4時重新分配了記憶體,所以第三個輸出語句結果為false;最後一個輸出語句結果也為false,說明當對str2進行修改時將建立一個新的物件,修改工作在新物件上完成,而原來引用的物件並沒有發生任何改變,str1仍然引用原有物件,而str2引用新物件,str1str2引用了兩個完全不同的物件。

 

擴充套件

關於Java    String類這種在修改享元物件時,先將原有物件複製一份,然後在新物件上再實施修改操作的機制稱為“Copy On Write”,大家可以自行查詢相關資料來進一步瞭解和學習“Copy On Write”機制,在此不作詳細說明。

14.7 享元模式總結

       當系統中存在大量相同或者相似的物件時,享元模式是一種較好的解決方案,它通過共享技術實現相同或相似的細粒度物件的複用,從而節約了記憶體空間,提高了系統效能。相比其他結構型設計模式,享元模式的使用頻率並不算太高,但是作為一種以“節約記憶體,提高效能”為出發點的設計模式,它在軟體開發中還是得到了一定程度的應用。

       1.主要優點

       享元模式的主要優點如下:

       (1) 可以極大減少記憶體中物件的數量,使得相同或相似物件在記憶體中只儲存一份,從而可以節約系統資源,提高系統效能。

       (2) 享元模式的外部狀態相對獨立,而且不會影響其內部狀態,從而使得享元物件可以在不同的環境中被共享。

       2.主要缺點

       享元模式的主要缺點如下:

       (1) 享元模式使得系統變得複雜,需要分離出內部狀態和外部狀態,這使得程式的邏輯複雜化。

       (2) 為了使物件可以共享,享元模式需要將享元物件的部分狀態外部化,而讀取外部狀態將使得執行時間變長。

       3.適用場景

       在以下情況下可以考慮使用享元模式:

       (1) 一個系統有大量相同或者相似的物件,造成記憶體的大量耗費。

       (2) 物件的大部分狀態都可以外部化,可以將這些外部狀態傳入物件中。

       (3) 在使用享元模式時需要維護一個儲存享元物件的享元池,而這需要耗費一定的系統資源,因此,應當在需要多次重複使用享元物件時才值得使用享元模式。

 

練習

Sunny軟體公司欲開發一個多功能文件編輯器,在文字文件中可以插入圖片、動畫、視訊等多媒體資料,為了節約系統資源,相同的圖片、動畫和視訊在同一個文件中只需儲存一份,但是可以多次重複出現,而且它們每次出現時位置和大小均可不同。試使用享元模式設計該文件編輯器。

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

相關文章