資訊中心 Info
當前位置:愛尚教育 > 資訊中心 >
Java設計模式之享元模式實例詳解
發布日期:2021-07-22 閱讀次數:

 

解釋一下概念:也就是說在一個系統中如果有多個相同的對象,那么只共享一份就可以了,不必每個都去實例化一個對象。比如說一個文本系統,每個字母定一個對象,那么大小寫字母一共就是52個,那么就要定義52個對象。如果有一個1M的文本,那么字母是何其的多,如果每個字母都定義一個對象那么內存早就爆了。那么如果要是每個字母都共享一個對象,那么就大大節約了資源。

在Flyweight模式中,由于要產生各種各樣的對象,所以在Flyweight(享元)模式中常出現Factory模式。Flyweight的內部狀態是用來共享的,Flyweight factory負責維護一個對象存儲池(Flyweight Pool)來存放內部狀態的對象。Flyweight模式是一個提高程序效率和性能的模式,會大大加快程序的運行速度.應用場合很多,下面舉個例子:

先定義一個抽象的Flyweight類:

  1.  
  2. package Flyweight;
  3. public abstract class Flyweight{
  4. public abstract void operation();
  5. }
  6.  
  7.  
復制代碼

實現一個具體類:

  1.  
  2. package Flyweight;
  3. public class ConcreteFlyweight extends Flyweight{
  4. private String string;
  5. public ConcreteFlyweight(String str){
  6. string = str;
  7. }
  8. public void operation()
  9. {
  10. System.out.println("Concrete---Flyweight : " + string);
  11. }
  12. }
  13.  
  14.  
復制代碼

實現一個工廠方法類:

  1.  
  2. package Flyweight;
  3. import java.util.Hashtable;
  4. public class FlyweightFactory{
  5. private Hashtable flyweights = new Hashtable();//----------------------------1
  6. public FlyweightFactory(){}
  7. public Flyweight getFlyWeight(Object obj){
  8. Flyweight flyweight = (Flyweight) flyweights.get(obj);//----------------2
  9. if(flyweight == null){//---------------------------------------------------3
  10. //產生新的ConcreteFlyweight
  11. flyweight = new ConcreteFlyweight((String)obj);
  12. flyweights.put(obj, flyweight);//--------------------------------------5
  13. }
  14. return flyweight;//---------------------------------------------------------6
  15. }
  16. public int getFlyweightSize(){
  17. return flyweights.size();
  18. }
  19. }
  20.  
  21.  
復制代碼

這個工廠方法類非常關鍵,這里詳細解釋一下:

在1處定義了一個Hashtable用來存儲各個對象;在2處選出要實例化的對象,在6處將該對象返回,如果在Hashtable中沒有要選擇的對象,此時變量flyweight為null,產生一個新的flyweight存儲在Hashtable中,并將該對象返回。

最后看看Flyweight的調用:

  1.  
  2. package Flyweight;
  3. import java.util.Hashtable;
  4. public class FlyweightPattern{
  5. FlyweightFactory factory = new FlyweightFactory();
  6. Flyweight fly1;
  7. Flyweight fly2;
  8. Flyweight fly3;
  9. Flyweight fly4;
  10. Flyweight fly5;
  11. Flyweight fly6;
  12. /** *//** Creates a new instance of FlyweightPattern */
  13. public FlyweightPattern(){
  14. fly1 = factory.getFlyWeight("Google");
  15. fly2 = factory.getFlyWeight("Qutr");
  16. fly3 = factory.getFlyWeight("Google");
  17. fly4 = factory.getFlyWeight("Google");
  18. fly5 = factory.getFlyWeight("Google");
  19. fly6 = factory.getFlyWeight("Google");
  20. }
  21. public void showFlyweight(){
  22. fly1.operation();
  23. fly2.operation();
  24. fly3.operation();
  25. fly4.operation();
  26. fly5.operation();
  27. fly6.operation();
  28. int objSize = factory.getFlyweightSize();
  29. System.out.println("objSize = " + objSize);
  30. }
  31. public static void main(String[] args){
  32. System.out.println("The FlyWeight Pattern!");
  33. FlyweightPattern fp = new FlyweightPattern();
  34. fp.showFlyweight();
  35. }
  36. }
  37.  
  38.  
復制代碼

下面是運行結果:

Concrete---Flyweight : Google
Concrete---Flyweight : Qutr
Concrete---Flyweight : Google
Concrete---Flyweight : Google
Concrete---Flyweight : Google
Concrete---Flyweight : Google
objSize = 2

我們定義了6個對象,其中有5個是相同的,按照Flyweight模式的定義“Google”應該共享一個對象,在實際的對象數中我們可以看出實際的對象卻是只有2個。

總結:

Flyweight(享元)模式是如此的重要,因為它能幫你在一個復雜的系統中大量的節省內存空間。在java語言中,String類型就是使用了享元模式。String對象是final類型,對象一旦創建就不可改變。在JAVA中字符串常量都是存在常量池中的,JAVA會確保一個字符串常量在常量池中只有一個拷貝。String a="abc",其中"abc"就是一個字符串常量。

熟悉java的應該知道下面這個例子:

  1.  
  2. String a = "hello";
  3. String b = "hello";
  4. if(a == b)
  5. System.out.println("OK");
  6. else
  7. System.out.println("Error");
  8.  
  9.  
復制代碼

輸出結果是:OK。可以看出if條件比較的是兩a和b的地址,也可以說是內存空間

核心總結,可以共享的對象,也就是說返回的同一類型的對象其實是同一實例,當客戶端要求生成一個對象時,工廠會檢測是否存在此對象的實例,如果存在那么直接返回此對象實例,如果不存在就創建一個并保存起來,這點有些單例模式的意思。通常工廠類會有一個集合類型的成員變量來用以保存對象,如hashtable,vector等。在java中,數據庫連接池,線程池等即是用享元模式的應用。

优彩-网址