- 目的 : 运用共享技术有效地支持大量细粒度的对象。
- 核心 : 区分对象的内部状态 (可共享的、不变的)和外部状态(不可共享的、变化的)。创建享元工厂管理共享的内部状态,客户端使用时传入外部状态。
- 场景 : 游戏中有大量相同类型的对象(如子弹、树木、士兵)、文本编辑器需要渲染大量字符(如字母、数字、符号)等。
首先有一个享元对象类
java
package flyweight;
public class Letter {
private String name;
public Letter(String name){
this.name = name;
}
public String getName(){
return this.name;
}
}
然后是享元工厂类
java
package flyweight;
import java.util.HashMap;
import java.util.Map;
public class LetterFactory {
private Map<String, Letter> map; // 对象池
private static LetterFactory instance = new LetterFactory(); // 1 私有静态实例 instance,通过静态方法 getInstance() 获取。
private LetterFactory(){
map = new HashMap<>(); // 2 私有构造函数,禁止外部直接实例化。
}
public static LetterFactory getInstance(){ // 3 确保 LetterFactory 全局只有一个实例。
return instance;
}
public synchronized void add(Letter letter){ // 确保同名 Letter 只保存一份
if(letter != null && !map.containsKey(letter.getName())){
map.put(letter.getName(), letter); // 存入缓存
}
System.out.println("map.size ==== " + map.size()); //通过对象池大小检验:是否同名 Letter 只保存一份
}
public Letter get(String name){
return map.get(name); // 从缓存中获取对象,避免重复创建
}
}
函数入口
java
package flyweight;
public class MainTest {
public static void main(String[] args) {
LetterFactory factory = LetterFactory.getInstance(); // 获取单例
String word = "success";
addLetterByName(factory, word);
getLetter(factory, word);
}
static void addLetterByName(LetterFactory factory, String word) {
for (char c : word.toCharArray()) { // 遍历字符串的每个字符
factory.add(new Letter(c + "")); // 创建 Letter 对象并存入工厂,c + "" 的作用是将 char 类型转换为 String 类型
}
}
static void getLetter(LetterFactory factory, String word) {
for (char c : word.toCharArray()) {
System.out.println(factory.get(c + "")); // 从缓存中获取对应的 对象并打印
}
}
}
终端输出:
map.size ==== 1 // 添加 s
map.size ==== 2 // 添加 u
map.size ==== 3 // 添加 c
map.size ==== 3 // 第二个 c,已存在,size不变
map.size ==== 4 // 添加 e
map.size ==== 4 // 第二个 s,已存在,size不变
map.size ==== 4 // 第三个 s,已存在,size不变
flyweight.Letter@4aa298b7 // s
flyweight.Letter@7d4991ad // u
flyweight.Letter@28d93b30 // c
flyweight.Letter@28d93b30 // c (复用)
flyweight.Letter@1b6d3586 // e
flyweight.Letter@4aa298b7 // s (复用)
flyweight.Letter@4aa298b7 // s (复用)

LetterFactory 和 Letter 是聚合关系,Letter 可以独立存在;
LetterFactory 和 map 是组合关系,map 是 LetterFactory 的组成部分。