一什么是享元模式二享元模式幾個角色抽象享元類Flyweight具體享元類FlyWeightAImlFlyWeightBIml享元工廠類FlyweightFactoiy客戶類Client三享元模式使用場景四代碼分析
設計模式的熟練掌握,能夠更容易理解系統的底層架構實現。

享元模式(Flyweight Pattern):以共享的方式高效的支持大量的細粒度對象。通過復用內存中已存在的對象,降低系統創建對象實例的性能消耗。 享元的英文是Flyweight,是一個來自體育方面的專業用語,在拳擊、摔跤和舉重比賽中特指最輕量的級別。把這個單詞移植到軟件工程中,也是用來表示特別小的對象,即細粒度的對象。至于為什么把Flyweight翻譯為“享元”,可以理解為共享元對象,也就是共享細粒度對象。 在面向對象中,大量細粒度對象的創建、銷毀及存儲所造成的資源和性能上的損耗,可能會在系統運行時形成瓶頸。那么該如何避免產生大量的細粒度對象,同時又不影響系統使用面向對象的方式進行操作呢?享元模式提供了一個比較好的解決方案。
uml類圖:

它是所有具體享元類的超類。為這些類規定出需要實現的公共接口,那些需要外蘊狀態(Exte的操作可以通過方法的參數傳入。抽象享元的接口使得享元變得可能,但是并不強制子類實行共享,因此并非所有的享元對象都是可以共享的。
具體享元類實現了抽象享元類所規定的接口。如果有內蘊狀態的話,必須負責為內蘊狀態提供存儲空間。享元對象的內蘊狀態必須與對象所處的周圍環境無關,從而使得享元對象可以在系統內共享。有時候具體享元類又稱為單純具體享元類,因為復合享元類是由單純具體享元角色通過復合而成的。
享元工廠類負責創建和管理享元對象。當一個客戶端對象請求一個享元對象的時候,享元工廠需要檢查系統中是否已經有一個符合要求的享元對象,如果已經有了,享元工廠角色就應當提供這個已有的享元對象;如果系統中沒有適當的享元對象的話,享元工廠角色就應當創建一個新的合適的享元對象。
客戶類需要自行存儲所有享元對象的外蘊狀態。
當系統中某個對象類型的實例較多的時候; 當系統設計時候,對象實例真正有區別的分類很少,例如對于拼音,如果對每個字母都初始化一個對象實例的話,這樣實例就太多了。使用享元模式只需要提前初始化基本拼音,就可以任意進行組裝成不同的拼音
網上很多例子,看著不太明白。使用字母進行舉例子通俗易懂。
CharactorFactory 工廠
package Chartflyweight;import java.util.Hashtable;public class CharactorFactory { PRivate Hashtable<String, FlyWeight> charactors = new Hashtable<String, FlyWeight>(); // 構造函數 public CharactorFactory() { charactors.put("A", new FlyWeightAIml()); charactors.put("B", new FlyWeightBIml()); } // 獲得指定字符實例 public FlyWeight getCharactor(String key) { FlyWeight charactor = (FlyWeight) charactors.get(key); if (charactor == null) { if (key.equals("A")) { charactor = new FlyWeightAIml(); } else if (key.equals("B")) { charactor = new FlyWeightBIml(); } charactors.put(key, charactor); } return charactor; }}FlyWeight 享元抽象類
package Chartflyweight;public abstract class FlyWeight { protected String charStr = ""; protected int fontSize; protected abstract void Operator(int fontSize); // 顯示方法 protected abstract void displayCharator();}FlyWeightAIml 具體實現類
package Chartflyweight;public class FlyWeightAIml extends FlyWeight { @Override protected void operator(int fontSize) { this.fontSize=fontSize; } public FlyWeightAIml() { this.charStr = "A"; this.fontSize=12; } @Override protected void displayCharator() { System.out.println("字符:" + this.charStr + ",大小:" + fontSize); }}FlyWeightBIml 具體實現類
package Chartflyweight;public class FlyWeightBIml extends FlyWeight { @Override protected void operator(int fontSize) { this.fontSize = fontSize; } public FlyWeightBIml() { this.charStr = "B"; this.fontSize = 12; } @Override protected void displayCharator() { System.out.println("字符:" + this.charStr + ",大小:" + fontSize); }}Client 測試類 1 ( 簡單的剔除外蘊狀態,在client中進行存儲)
package Chartflyweight;//如何有特別多的外部狀態,則需要很多的函數,函數進行抽取public class Clinet { public static void main(String[] args) { FlyWeightAIml a = new FlyWeightAIml(); FlyWeightBIml b = new FlyWeightBIml(); // 顯示字符A display(a, 12); // 顯示字符B display(b, 14); } // 設置字符的大小 public static void display(FlyWeight objChar, int nSize) { try { System.out.println("字符:" + objChar.charStr + ",大小:" + nSize); } catch (Exception err) { } }}測試類2 (考慮到復用性,將外蘊狀態作為參數在使用時候進行傳遞)
package Chartflyweight;//如何有特別多的外部狀態,則需要很多的函數,函數進行抽取public class Clinet2 { public static void main(String[] args) { FlyWeightAIml a = new FlyWeightAIml(); FlyWeightBIml b = new FlyWeightBIml(); // 設置字符A的大小 a.operator(12); // 顯示字符B a.displayCharator(); // 設置字符B的大小 b.operator(14); // 顯示字符B b.displayCharator(); }}輸出結果:
字符:A,大小:12 字符:B,大小:14
上面代碼內蘊共享對象是 A,B ,而外蘊不共享狀態是 fontSize.
引用個例子:
享元模式在一般的項目開發中并不常用,而是常常應用于系統底層的開發,以便解決系統的性能問題。 Java和.Net中的String類型就是使用了享元模式。如果在Java或者.NET中已經創建了一個字符串對象s1,那么下次再創建相同的字符串s2的時候,系統只是把s2的引用指向s1所引用的具體對象,這就實現了相同字符串在內存中的共享。如果每次執行s1=“abc”操作的時候,都創建一個新的字符串對象的話,那么內存的開銷會很大。 如果大家有興趣的話,可以用下面的程序進行測試,就會知道s1和s2的引用是否一致: Java代碼:
String s1 = "測試字符串1";String s2 = "測試字符串1";//“==”用來判斷兩個對象是否是同一個,equals判斷字符串的值是否相等if( s1 == s2 ){System.out.println("兩者一致");}else{System.out.println("兩者不一致");}程序運行后,輸出的結果為“兩者一致”,這說明String類的設計采用了享元模式。如果s1的內容發生了變化,比如執行了s1 += “變化”的語句,那么s1與s2的引用將不再一致。
Java DEMO :http://pan.baidu.com/s/1bpKhdpl
引用: 享元(Flyweight)模式 http://www.cnblogs.com/zhenyulu/articles/55793.html 設計模式之享元模式 http://blog.csdn.net/wanghao72214/article/details/4046182 Flyweight模式的學習 http://supercrsky.iteye.com/blog/372714
新聞熱點
疑難解答