JAVA設計模式----享元模式
解釋一下概念:也就是說在一個系統中如果有多個相同的物件,那麼只共享一份就可以了,不必每個都去例項化一個物件。比如說一個文本系統,每個字母定一個物件,那麼大小寫字母一共就是52個,那麼就要定義52個物件。如果有一個1M的文字,那麼字母是何其的多,如果每個字母都定義一個物件那麼記憶體早就爆了。那麼如果要是每個字母都共享一個物件,那麼就大大節約了資源。
在Flyweight模式中,由於要產生各種各樣的物件,所以在Flyweight(享元)模式中常出現Factory模式。Flyweight的內部狀態是用來共享的,Flyweight factory負責維護一個物件儲存池(Flyweight Pool)來存放內部狀態的物件。Flyweight模式是一個提高程式效率和效能的模式,會大大加快程式的執行速度.應用場合很多,下面舉個例子:
先定義一個抽象的Flyweight類:
package Flyweight;
public abstract class Flyweight{
public abstract void operation();
}
實現一個具體類:
package Flyweight; public class ConcreteFlyweight extends Flyweight{ private String string; public ConcreteFlyweight(String str){ string = str; } public void operation() { System.out.println("Concrete---Flyweight : " + string); } }
實現一個工廠方法類:
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 } public int getFlyweightSize(){ return flyweights.size(); } }
這個工廠方法類非常關鍵,這裡詳細解釋一下:
在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");
}
public void showFlyweight(){
fly1.operation();
fly2.operation();
fly3.operation();
fly4.operation();
fly5.operation();
fly6.operation();
int objSize = factory.getFlyweightSize();
System.out.println("objSize = " + objSize);
}
public static void main(String[] args){
System.out.println("The FlyWeight Pattern!");
FlyweightPattern fp = new FlyweightPattern();
fp.showFlyweight();
}
}
下面是執行結果:
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的應該知道下面這個例子:
String a = "hello";
String b = "hello";
if(a == b)
System.out.println("OK");
else
System.out.println("Error");
輸出結果是:OK。可以看出if條件比較的是兩a和b的地址,也可以說是記憶體空間
核心總結,可以共享的物件,也就是說返回的同一型別的物件其實是同一例項,當客戶端要求生成一個物件時,工廠會檢測是否存在此物件的例項,如果存在那麼直接返回此物件例項,如果不存在就建立一個並儲存起來,這點有些單例模式的意思。通常工廠類會有一個集合型別的成員變數來用以儲存物件,如hashtable,vector等。在java中,資料庫連線池,執行緒池等即是用享元模式的應用。