Flyweight 定义:
避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类).
面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞
大,比如,字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗
费内存,那么我们还是要"求同存异",找出这些对象群的共同点,设计一个元类,封装可以被
共享的类,另外,还有一些特性是取决于应用(context),是不可共享的,这也 Flyweight 中两
个重要概念内部状态 intrinsic 和外部状态 extrinsic 之分.
这个是对这个模式的定义,我觉得最重要的是能够对要处理对象进行内部状态和外部状态的区分,这样对象的内部状态就能共享,但是很多例子都把flyweight模式写成一pool,然后对pool里的对象进行共享,这样貌似偏离了flyweight模式的初衷而且效果不理想。下面是网上找到的例子,比较符合模式的意图
1.定义抽象接口
public interface Font { public void SetFont(String color, int size); public void GetFont(); }
2.接口的具体实现
public class ConcreteFont implements Font { private String color; private int size; private FontInner inner; public ConcreteFont(FontInner s) { inner = s; // id = "The char is: " + s; } public void SetFont(String _color, int _size) { color = _color; size = _size; } public void GetFont() { System.out.println("String :" + inner.getFontString() + "--- color is:" + color + "--- size is:" + size); } }
3.可以共享的内部状态
public class FontInner { private String fontString; private String status; public FontInner(String fontString, String status) { this.setFontString(fontString); this.setStatus(status); } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getFontString() { return fontString; } public void setFontString(String fontString) { this.fontString = fontString; } }
4.FontInnerFactory负责维护一个 Flyweight 池(存放内部状态)
public class FontInnerFactory { private Hashtable<String, FontInner> charHashTable = new Hashtable(); public FontInnerFactory() { } public FontInner GetFlyWeight(String fontString, String status) { if (charHashTable.get(fontString) != null) { return charHashTable.get(fontString); } else { FontInner tmp = new FontInner(fontString, status); charHashTable.put(fontString, tmp); return tmp; } } public Hashtable GetFactory() { return charHashTable; } }
测试:
import java.util.ArrayList; import java.util.Hashtable; import java.util.List; public class Main { public static void main(String[] args) { int[] size = { 8, 9, 10, 11, 12 }; String[] color = { "FFFFFF", "000000", "FF00FF", "CCCCCC", "111111" }; FontInnerFactory fontInnerFactory = new FontInnerFactory(); String aString = "A test string"; List<Font> fontList = new ArrayList(); for (int i = 0; i < aString.length(); i++) { int j = 0; j = (int) Math.floor(Math.random() * 5); // System.out.println("j is:" + j + "---" +aString.substring(i, // i+1)); ConcreteFont font = new ConcreteFont(fontInnerFactory.GetFlyWeight( aString.substring(i, i + 1), "")); font.SetFont(color[j], size[j]); fontList.add(font); } Hashtable myHashTable = fontInnerFactory.GetFactory(); System.out.println("Hash table size is:" + myHashTable.size()); for (Font font : fontList) { font.GetFont(); } } }
这里ConcreteFont中的FontInner 就是内部对象,是可以共享的不用每次都创建,color和size是外部对象是根据上下文环境进行设置的,从结果看,打印的String字符有十多个,但fontInnerFactory中map里对象数只有9个,内部对象得到共享。