Java設計模式之Flyweight模式

GOF:運用共享技術有效地支持大量細粒度的對象。

 

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

 

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

 

先定義一個抽象的Flyweight類:

 

package Flyweight;

 

public abstract class Flyweight

...

{

 public abstract void operation();

}//end abstract class Flyweight

 

在實現一個具體類:

 

package Flyweight;

 

public class ConcreteFlyweight extends Flyweight

...

{

 private String string;

 public ConcreteFlyweight(String str)

 ...

 {

string = str;

 }//end ConcreteFlyweight(...)

 

 public void operation()

 ...

 {

System.out.println("Concrete---Flyweight : " + string);

 }//end operation()

 

}//end class ConcreteFlyweight

 

實現一個工廠方法類:

 

package Flyweight;

import java.util.Hashtable;

 

public class FlyweightFactory

...

{

 private Hashtable flyweights = new Hashtable();//----------------------------1

 public FlyweightFactory() ...{}

 

 public Flyweight getFlyWeight(Object obj)

 ...

 {

Flyweight flyweight = (Flyweight) flyweights.get(obj);//----------------2

 

if(flyweight == null) ...{//---------------------------------------------------3

 //產生新的ConcreteFlyweight

 flyweight = new ConcreteFlyweight((String)obj);

 flyweights.put(obj, flyweight);//--------------------------------------5

}

return flyweight;//---------------------------------------------------------6

 }//end GetFlyWeight(...)

 

 public int getFlyweightSize()

 ...

 {

return flyweights.size();

 }

}//end class FlyweightFactory

 

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

 

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

最後看看Flyweight的調用:

 

package Flyweight;

import java.util.Hashtable;

 

public class FlyweightPattern ...{

 FlyweightFactory factory = new FlyweightFactory();

 Flyweight fly1;

 Flyweight fly2;

 Flyweight fly3;

 Flyweight fly4;

 Flyweight fly5;

 Flyweight fly6;

 

 /** *//** Creates a new instance of FlyweightPattern */

 public FlyweightPattern() ...{

fly1 = factory.getFlyWeight("Google");

fly2 = factory.getFlyWeight("Qutr");

fly3 = factory.getFlyWeight("Google");

fly4 = factory.getFlyWeight("Google");

fly5 = factory.getFlyWeight("Google");

fly6 = factory.getFlyWeight("Google");

 }//end FlyweightPattern()

 

 public void showFlyweight()

 ...

 {

fly1.operation();

fly2.operation();

fly3.operation();

fly4.operation();

fly5.operation();

fly6.operation();

int objSize = factory.getFlyweightSize();

System.out.println("objSize = " + objSize);

 }//end showFlyweight()

 

 public static void main(String[] args)

 ...

 {

System.out.println("The FlyWeight Pattern!");

FlyweightPattern fp = new FlyweightPattern();

fp.showFlyweight();

 }//end main(...)

}//end class FlyweightPattern

 

下面是運行結果:

 

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個。

 

下面給出一個簡易的UML圖:

 

 

總結:

 

Flyweight(享元)模式是如此的重要,因爲它能幫你在一個複雜的系統中大量的節省內存空間。在GOF的書中舉了文本處理的例子,我覺得非常恰當。那麼,在Java中String這個類型比較特殊,爲什麼呢,看下面的例子:

 

String a = "hello";

String b = "hello";

if(a == b)

 System.out.println("OK");

else

 System.out.println("Error");

 

輸出結果是:OK。稍有經驗的人都可以看出if條件比較的是兩a和b的地址,也可以說是內存空間。那麼Sting的實現是不是使用了Flyweight模式呢,不得而知,到現在還沒有研究過。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章