享元模式

129 阅读2分钟

背景

享元模式又叫做 FlyWeight 模式,一言以蔽之就是“通过尽量共享实例来避免 new 出实例”,当需要某个实例时,并不总是通过new 关键字来生成实例,而是尽量共用已经存在的实例。

登场角色

Flyweight 轻量级

按照通常方式编写程序会导致程序变重,所以如果可以能够共享实例会比较好,而Flyweight表示的就是那些实例会被共享的类;

FlyweightFactory 轻量级工厂

FlyweightFactory 角色是生成Flyweight 角色的工厂,在工厂中生成Flyweight 角色可以实现共享实例;

Client 请求者

Client 角色使用 FlyweightFactory 角色来生成 Flyweight 角色;

类图

示例代码

实例是一个显示特殊字符串的代码,将每个不同的字符先保存起来,根据字符串中不同的字符从Factory获取即可,不必每次都创建;

BigChar

public class BigChar {
    private char charName;

    private String fontdata;

    public BigChar(char charName) {
        this.charName = charName;
        try {
            String line;
            BufferedReader bufferedReader = new BufferedReader(new FileReader(charName + ".txt"));
            StringBuffer stringBuffer = new StringBuffer();
            while ((line = bufferedReader.readLine()) != null) {
                stringBuffer.append(line);
                stringBuffer.append("\n");
            }
            bufferedReader.close();
            fontdata = stringBuffer.toString();
        } catch (IOException e) {
            fontdata = charName + "?";
        }
    }

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

BigCharFactory

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

    private static BigCharFactory singleton = new BigCharFactory();

    public static BigCharFactory getInstance() {
        return singleton;
    }

    private BigCharFactory() {
    }

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

        return bigChar;
    }
}

BigString

public class BigString {

    private BigChar[] bigChars;

    public BigString(String string) {
        char[] chars = string.toCharArray();
        int length = chars.length;
        bigChars = new BigChar[length];
        for (int i = 0; i < chars.length; i++) {
            bigChars[i] = BigCharFactory.getInstance().getBigChar(chars[i]);
        }
    }

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

功能分析

  1. 在决定 Flyweight 角色中的字段时,需要精挑细选,只将那些真正应该在多个地方共享的字段定义在 Flyweight 角色中即可;
  2. 不要让垃圾回收器共享实例 回收掉,因为 pool 字段一直管理着这些共享角色,一直引用着他们,不会被垃圾回收器回收;
  3. 可以减少内存的使用量,减少生成实例所花费的时间