共享对象,避免浪费-flyweight模式

852 阅读1分钟

1、引入

flyweight,从字面意思来看,可以飞的质量,这么来说是很轻了,它的译义也为轻量级。

在程序设计中,往往有这样一种对象,它在某个场景下大量被使用,如果一种通过new的方式创建的话,会导致大量的内存占用。

而flyweight模式,正是通过尽量共享对象的方式来减少资源的浪费。

2、示例

有这样一种大字符类,其通过多个小字符组成图像,如下:

image.png 如果在使用它们的时候频繁创建,那么会占用大量资源,因此在这里使用flyweight模式。

2.2.1、BigChar类

public class BigChar {
    private char charName;

    private String fontData;

    public BigChar(char charName) {
        this.charName = charName;
        try {
            BufferedReader reader = new BufferedReader(new FileReader(
                    "./src/flyweight/example/big" + charName + ".txt"  //通过txt存储
            ));
            String line;
            StringBuffer buffer = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
                buffer.append("\n");
            }
            reader.close();
            this.fontData=buffer.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void print() {
        System.out.println(fontData);
    }
}

2.2、BigCharFactory类

通过单例的工厂操作BigChar,实现资源共享

public class BigCharFactory {
    private HashMap pool=new HashMap<Character,BigChar>();
    private static BigCharFactory singleton=new BigCharFactory();

    private BigCharFactory() {
    }

    public static BigCharFactory getInstance() {
        return singleton;
    }

    public synchronized BigChar getBigChar(char charName) {
        BigChar bigChar = (BigChar)pool.get(charName);
        if (bigChar == null) {
            bigChar=new BigChar(charName);
            pool.put(charName, bigChar);
        }
        return bigChar;
    }
}

2.3、BigString类

将string对象转化为BigChar的类

public class BigString {
    private BigChar[] bigChars;

    public BigString(String str) {
        BigCharFactory bigCharFactory = BigCharFactory.getInstance();
        bigChars=new BigChar[str.length()];
        for (int i = 0; i < bigChars.length; i++) {
            bigChars[i]=bigCharFactory.getBigChar(str.charAt(i));
        }
    }

    public void print() {
        for (int i = 0; i < bigChars.length; i++) {
            bigChars[i].print();
        }
    }
}

2.4、测试

public class Main {
    public static void main(String[] args) {
        BigString bigString = new BigString("12");
        bigString.print();
    }
}

运行结果:

image.png

3、tips

  • flyweight模式的应用要求在一处地方修改对象不能影响别处,因为是共享的对象。
  • 在本例中采用的池化技术,在许多地方也有用到,是flyweight模式的体现,如:
    • 字符串常量池
    • 数据库连接池
    • 包装类Integer的cache池
    • etc