Flyweight 定義:
避免大量擁有相同內容的小類的開銷(如耗費記憶體),使大家共用一個類(元類).
物件導向語言的原則就是一切都是對象,但是如果真正使用起來,有時對象數可能顯得很龐
大,比如,文書處理軟體,如果以每個文字都作為一個對象,幾千個字,對象數就是幾千,無疑耗
費記憶體,那麼我們還是要"求同存異",找出這些對象群的共同點,設計一個元類,封裝可以被
共用的類,另外,還有一些特性是取決於應用(context),是不可共用的,這也 Flyweight 中兩
個重要概念內部狀態 intrinsic 和外部狀態 extrinsic 之分.
這個是對這個模式的定義,我覺得最重要的是能夠對要處理對象進行內部狀態和外部狀態的區分,這樣對象的內部狀態就能共用,但是很多例子都把flyweight模式寫成一pool,然後對pool裡的對象進行共用,這樣貌似偏離了flyweight模式的初衷而且效果不理想。下面是網上找到的例子,比較符合模式的意圖
1.定義抽象介面
public interface Font {<br />public void SetFont(String color, int size);</p><p>public void GetFont();<br />}
2.介面的具體實現
public class ConcreteFont implements Font {<br />private String color;<br />private int size;<br />private FontInner inner;</p><p>public ConcreteFont(FontInner s) {<br />inner = s;<br />// id = "The char is: " + s;<br />}</p><p>public void SetFont(String _color, int _size) {<br />color = _color;<br />size = _size;<br />}</p><p>public void GetFont() {<br />System.out.println("String :" + inner.getFontString() + "--- color is:"<br />+ color + "--- size is:" + size);<br />}<br />}
3.可以共用的內部狀態
public class FontInner {</p><p>private String fontString;</p><p>private String status;</p><p>public FontInner(String fontString, String status) {<br />this.setFontString(fontString);<br />this.setStatus(status);<br />}</p><p>public String getStatus() {<br />return status;<br />}</p><p>public void setStatus(String status) {<br />this.status = status;<br />}</p><p>public String getFontString() {<br />return fontString;<br />}</p><p>public void setFontString(String fontString) {<br />this.fontString = fontString;<br />}</p><p>}<br />
4.FontInnerFactory負責維護一個 Flyweight 池(存放內部狀態)
public class FontInnerFactory {<br />private Hashtable<String, FontInner> charHashTable = new Hashtable();</p><p>public FontInnerFactory() {<br />}</p><p>public FontInner GetFlyWeight(String fontString, String status) {<br />if (charHashTable.get(fontString) != null) {<br />return charHashTable.get(fontString);<br />} else {<br />FontInner tmp = new FontInner(fontString, status);<br />charHashTable.put(fontString, tmp);<br />return tmp;<br />}<br />}</p><p>public Hashtable GetFactory() {<br />return charHashTable;<br />}<br />}
測試:
import java.util.ArrayList;<br />import java.util.Hashtable;<br />import java.util.List;</p><p>public class Main {<br />public static void main(String[] args) {<br />int[] size = { 8, 9, 10, 11, 12 };<br />String[] color = { "FFFFFF", "000000", "FF00FF", "CCCCCC", "111111" };<br />FontInnerFactory fontInnerFactory = new FontInnerFactory();<br />String aString = "A test string";<br />List<Font> fontList = new ArrayList();<br />for (int i = 0; i < aString.length(); i++) {<br />int j = 0;<br />j = (int) Math.floor(Math.random() * 5);<br />// System.out.println("j is:" + j + "---" +aString.substring(i,<br />// i+1));<br />ConcreteFont font = new ConcreteFont(fontInnerFactory.GetFlyWeight(<br />aString.substring(i, i + 1), ""));<br />font.SetFont(color[j], size[j]);<br />fontList.add(font);<br />}</p><p>Hashtable myHashTable = fontInnerFactory.GetFactory();<br />System.out.println("Hash table size is:" + myHashTable.size());<br />for (Font font : fontList) {<br />font.GetFont();<br />}<br />}<br />}
這裡ConcreteFont中的FontInner 就是內部對象,是可以共用的不用每次都建立,color和size是外部對象是根據上下文環境進行設定的,從結果看,列印的String字元有十多個,但fontInnerFactory中map裡對象數只有9個,內部對象得到共用。