运用共享技术有效地支持大量细粒度对象的复用。
理解享元模式:通过共享大量细粒度对象,大幅减少内存占用
掌握内部状态(可共享)与外部状态(随场景变化)的区分方法
理解 Flyweight Factory 的作用:管理共享对象池,确保相同内部状态只创建一个实例
了解享元模式在文本编辑器、游戏场景、森林植树等场景中的应用
享元将可共享的内在状态集中到 treetype,每个 tree 只保留外在坐标
/** 享元对象:存储可共享的内部状态(树的种类信息) */
public class TreeType {
public String name;
public String color;
public String texture;
public TreeType(String name, String color, String texture) {
this.name = name; this.color = color; this.texture = texture;
}
public void draw(int x, int y) {
System.out.println("Drawing " + name + " tree at (" + x + "," + y + ")");
}
}/** 树对象:存储外部状态(坐标),引用共享的 TreeType */
public class Tree {
private int x, y;
private TreeType type;
public Tree(int x, int y, TreeType type) {
this.x = x; this.y = y; this.type = type;
}
public void draw() {
type.draw(x, y);
}
}import java.util.HashMap;
/** 享元工厂:管理 TreeType 对象池,相同种类只创建一个实例 */
public class TreeFactory {
private static HashMap<String, TreeType> treeTypes =
new HashMap<>();
public static TreeType getTreeType(String name,
String color, String texture) {
String key = name + "_" + color + "_" + texture;
if (!treeTypes.containsKey(key)) {
treeTypes.put(key, new TreeType(name, color, texture));
}
return treeTypes.get(key);
}
}import java.util.ArrayList;
import java.util.List;
/** 森林:持有所有树对象,演示享元模式节省内存 */
public class Forest {
private List<Tree> trees = new ArrayList<>();
public void plantTree(int x, int y, String name,
String color, String texture) {
TreeType type = TreeFactory.getTreeType(name, color, texture);
Tree tree = new Tree(x, y, type);
trees.add(tree);
}
public int size() { return trees.size(); }
}public class Demo {
public static void main(String[] args) {
Forest forest = new Forest();
// 种植 100 万棵树,但只共享 2 种 TreeType
for (int i = 0; i < 500_000; i++) {
forest.plantTree(i, i, "Oak", "Green", "oak.png");
forest.plantTree(i, i + 1, "Pine", "DarkGreen", "pine.png");
}
System.out.println("Trees planted: " + forest.size());
}
}TreeType(name/color/texture)所有树共享,是内部状态;Tree 的 x/y 坐标随每次种植变化,是外部状态。
TreeFactory 用 Map 缓存已创建的 TreeType,getTreeType() 先查池,有则直接返回,无则创建并存入池。
100 万棵树(100 万 Tree 对象)只占用约 7 MB(TreeType 共享),而非约 36 MB(每树独立全部状态)。
文本编辑器(共享字符样式)、游戏(共享树木/石头/敌人贴图)、GUI(共享按钮/图标样式)、字符串池、线程池。