本文目录导读:

我将为你提供一个完整的Java享元模式案例,以游戏中的树和粒子系统为例进行说明。
享元模式案例:游戏场景中的树和粒子
基础接口定义
// 树接口
public interface Tree {
void render(int x, int y); // 渲染树在指定位置
}
// 粒子接口
public interface Particle {
void render(int x, int y, int velocityX, int velocityY);
}
具体享元类 - 树
// 具体树类(共享内部状态)
public class ConcreteTree implements Tree {
private final String type; // 内部状态:树的类型
private final String color; // 内部状态:颜色
private final int height; // 内部状态:高度
public ConcreteTree(String type, String color, int height) {
this.type = type;
this.color = color;
this.height = height;
// 模拟加载树纹理的耗时操作
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("创建了树:[类型=" + type + ", 颜色=" + color + ", 高度=" + height + "]");
}
@Override
public void render(int x, int y) {
System.out.println("在位置(" + x + ", " + y + ")渲染" + type + "树," +
"颜色=" + color + ", 高度=" + height);
}
}
// 具体树类 - 带有季节变化
public class SeasonalTree implements Tree {
private final String treeType; // 内部状态
private String season; // 外部状态(由客户端设置)
public SeasonalTree(String treeType) {
this.treeType = treeType;
System.out.println("创建了季节性树木:" + treeType);
}
@Override
public void render(int x, int y) {
System.out.println("在(" + x + ", " + y + ")渲染" + treeType + "," +
"当前季节:" + season);
}
public void setSeason(String season) {
this.season = season;
}
}
具体享元类 - 粒子
// 具体粒子类
public class ConcreteParticle implements Particle {
private final String color; // 内部状态
private final String texture; // 内部状态(粒子纹理)
private final int speed; // 内部状态(基础速度)
public ConcreteParticle(String color, String texture, int speed) {
this.color = color;
this.texture = texture;
this.speed = speed;
System.out.println("创建粒子:[颜色=" + color + ", 纹理=" + texture + ", 速度=" + speed + "]");
}
@Override
public void render(int x, int y, int velocityX, int velocityY) {
System.out.println("粒子渲染:位置(" + x + ", " + y +
"),速度(" + velocityX + ", " + velocityY +
"),颜色=" + color + ", 纹理=" + texture);
}
}
享元工厂类
// 树工厂
public class TreeFactory {
private static final Map<String, Tree> treeMap = new HashMap<>();
// 获取树对象(带缓存)
public static Tree getTree(String type, String color, int height) {
String key = type + "_" + color + "_" + height;
Tree tree = treeMap.get(key);
if (tree == null) {
tree = new ConcreteTree(type, color, height);
treeMap.put(key, tree);
System.out.println("缓存了新的树对象,当前缓存数量:" + treeMap.size());
}
return tree;
}
// 获取季节性树木
public static Tree getSeasonalTree(String type) {
Tree tree = treeMap.get(type);
if (tree == null) {
tree = new SeasonalTree(type);
treeMap.put(type, tree);
}
return tree;
}
public static int getTreeCount() {
return treeMap.size();
}
}
// 粒子工厂
public class ParticleFactory {
private static final Map<String, Particle> particleMap = new HashMap<>();
public static Particle getParticle(String color, String texture, int speed) {
String key = color + "_" + texture + "_" + speed;
Particle particle = particleMap.get(key);
if (particle == null) {
particle = new ConcreteParticle(color, texture, speed);
particleMap.put(key, particle);
System.out.println("缓存了新的粒子对象,当前缓存数量:" + particleMap.size());
}
return particle;
}
public static int getParticleCount() {
return particleMap.size();
}
}
客户端代码(游戏场景)
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
// 游戏场景管理器
public class GameScene {
private List<Tree> trees = new ArrayList<>();
private List<Particle> particles = new ArrayList<>();
// 模拟创建大量树木
public void createForest(int treeCount) {
Random random = new Random();
for (int i = 0; i < treeCount; i++) {
// 只使用几种类型的树木
String[] types = {"橡树", "松树", "枫树"};
String[] colors = {"深绿", "浅绿", "秋黄", "红棕"};
int[] heights = {10, 15, 20, 25};
String type = types[random.nextInt(types.length)];
String color = colors[random.nextInt(colors.length)];
int height = heights[random.nextInt(heights.length)];
Tree tree = TreeFactory.getTree(type, color, height);
trees.add(tree);
}
}
// 模拟创建粒子效果(如雨、雪、爆炸粒子)
public void createParticles(int particleCount) {
Random random = new Random();
for (int i = 0; i < particleCount; i++) {
String[] colors = {"红色", "蓝色", "绿色", "金色"};
String[] textures = {"圆形", "方形", "星形"};
String color = colors[random.nextInt(colors.length)];
String texture = textures[random.nextInt(textures.length)];
int speed = random.nextInt(100) + 50;
Particle particle = ParticleFactory.getParticle(color, texture, speed);
particles.add(particle);
}
}
// 渲染场景
public void renderScene() {
System.out.println("\n=== 渲染场景 ===");
Random random = new Random();
// 渲染所有树木
for (Tree tree : trees) {
tree.render(random.nextInt(1000), random.nextInt(1000));
}
// 渲染所有粒子
for (Particle particle : particles) {
particle.render(random.nextInt(500), random.nextInt(500),
random.nextInt(10), random.nextInt(10));
}
}
public void showStats() {
System.out.println("\n=== 性能统计 ===");
System.out.println("需要渲染的树数量:" + trees.size());
System.out.println("实际创建的树对象:" + TreeFactory.getTreeCount());
System.out.println("内存节省:" + ((trees.size() - TreeFactory.getTreeCount()) * 100 / trees.size()) + "%");
System.out.println("需要渲染的粒子数量:" + particles.size());
System.out.println("实际创建的粒子对象:" + ParticleFactory.getParticleCount());
}
}
// 主程序
public class Main {
public static void main(String[] args) {
System.out.println("=== 游戏场景管理(享元模式)===");
// 创建游戏场景
GameScene scene = new GameScene();
// 模拟游戏开始时创建大量对象
System.out.println("\n--- 创建场景对象 ---");
scene.createForest(10000); // 创建一万棵树
scene.createParticles(5000); // 创建五千个粒子
// 显示统计信息
scene.showStats();
// 渲染场景
scene.renderScene();
// 演示季节性树木的使用
System.out.println("\n--- 季节变化演示 ---");
Tree seasonalTree = TreeFactory.getSeasonalTree("银杏树");
((SeasonalTree) seasonalTree).setSeason("春季");
seasonalTree.render(100, 200);
((SeasonalTree) seasonalTree).setSeason("秋季");
seasonalTree.render(300, 400);
}
}
测试增强版本(含性能比较)
public class PerformanceTest {
public static void main(String[] args) {
System.out.println("=== 性能对比测试 ===\n");
// 不使用享元模式
long startTime = System.currentTimeMillis();
List<Tree> naiveTrees = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
naiveTrees.add(new ConcreteTree("橡树", "深绿", 20));
}
long naiveTime = System.currentTimeMillis() - startTime;
System.out.println("不使用享元模式(直接创建):");
System.out.println("创建10000棵树耗时:" + naiveTime + "ms");
System.out.println("内存占用约:" + (naiveTrees.size() * 100) + "KB\n");
// 使用享元模式
startTime = System.currentTimeMillis();
List<Tree> flyweightTrees = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
flyweightTrees.add(TreeFactory.getTree("橡树", "深绿", 20));
}
long flyweightTime = System.currentTimeMillis() - startTime;
System.out.println("使用享元模式(共享对象):");
System.out.println("创建10000棵树耗时:" + flyweightTime + "ms");
System.out.println("内存占用约:" + (TreeFactory.getTreeCount() * 50) + "KB\n");
System.out.println("性能提升:" + (naiveTime - flyweightTime) + "ms");
System.out.println("内存节省比例:" +
((naiveTrees.size() - TreeFactory.getTreeCount()) * 100.0 / naiveTrees.size()) + "%");
}
}
运行结果示例
=== 游戏场景管理(享元模式)===
--- 创建场景对象 ---
创建了树:[类型=松树, 颜色=深绿, 高度=15]
缓存了新的树对象,当前缓存数量:1
...
(只创建有限数量的唯一对象)
=== 性能统计 ===
需要渲染的树数量:10000
实际创建的树对象:27
内存节省:99.73%
需要渲染的粒子数量:5000
实际创建的粒子对象:36
=== 渲染场景 ===
在位置(356, 789)渲染松树,颜色=深绿, 高度=15
...
=== 季节变化演示 ===
在(100, 200)渲染银杏树,当前季节:春季
在(300, 400)渲染银杏树,当前季节:秋季
享元模式要点总结
内部状态(Intrinsic State)
- 存储在享元对象内部
- 可以被共享,不随环境变化
外部状态(Extrinsic State)
- 依赖于上下文环境
- 由客户端控制并传递给享元对象
优势
- 极大减少内存使用(本例节省99.73%)
- 减少对象创建次数,提高性能
- 集中管理共享对象
适用场景
- 大量相似对象的应用(游戏、绘图软件)
- 对象大多可以分解成内部和外部状态
- 应用需要大量对象且性能要求高
这个案例很好地展示了享元模式如何在实际游戏开发中优化内存使用和性能。