解釋一下概念:也就是說在一個系統中若是有多個相同的對象,那麼只共享一份就能夠了,沒必要每一個都去實例化一個對象。好比說一個文本系統,每一個字母定一個對象,那麼大小寫字母一共就是52個,那麼就要定義52個對象。若是有一個1M的文本,那麼字母是何其的多,若是每一個字母都定義一個對象那麼內存早就爆了。那麼若是要是每一個字母都共享一個對象,那麼就大大節約了資源。
在Flyweight模式中,因爲要產生各類各樣的對象,因此在Flyweight(享元)模式中常出現Factory模式。Flyweight的內部狀態是用來共享的,Flyweight factory負責維護一個對象存儲池(Flyweight Pool)來存放內部狀態的對象。Flyweight模式是一個提升程序效率和性能的模式,會大大加快程序的運行速度.應用場合不少,下面舉個例子:
先定義一個抽象的Flyweight類:java
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(); } }
下面是運行結果:code
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中,數據庫鏈接池,線程池等便是用享元模式的應用。
字符串