设计模式-享源模式
什么是享元模式?
享元模式是一种结构型设计模式,它通过共享技术来有效地支持大量细粒度的对象。享元模式通过共享已经存在的对象来减少创建对象的数量,从而减少内存占用和提高性能。
享元模式包含以下角色:
- 享元接口(Flyweight):声明一个接口,通过它可以接受并作用于外部状态
- 具体享元类(ConcreteFlyweight):实现享元接口,并为内部状态增加存储空间
- 非共享具体享元类(UnsharedConcreteFlyweight):不需要共享的Flyweight子类
- 享元工厂(FlyweightFactory):创建并管理flyweight对象,确保合理地共享flyweight
享元模式的优缺点
优点:
- 减少内存使用:通过共享对象,大量减少对象的创建,节省内存空间
- 提高性能:减少对象创建和垃圾回收的开销
- 系统资源优化:有效利用系统资源,提高系统整体性能
缺点: - 增加复杂性:需要区分内部状态和外部状态,增加了系统复杂性
- 线程安全问题:共享对象可能带来线程安全问题,需要额外处理
- 状态管理复杂:需要仔细管理对象的内部状态和外部状态
什么场景下使用享元模式
- 系统中有大量相似对象
- 这些对象的大部分状态都可以外部化
- 按照内部状态分成很多组,当把对象作为组来处理时,同一组的对象可以被共享
- 需要缓冲池的场景
- 对象创建开销大,但可以共享的场景
代码举例
// 享元接口 - 地形类型
interface Terrain {
void render(int x, int y, String instanceData);
boolean isWalkable();
int getMovementCost();
}
// 具体享元类 - 草地地形(内部状态:类型属性)
class GrassTerrain implements Terrain {
private static final String TYPE = "Grass";
private static final boolean WALKABLE = true;
private static final int MOVEMENT_COST = 1;
@Override
public void render(int x, int y, String instanceData) {
System.out.printf("渲染草地地形在(%d,%d),实例数据:%s%n", x, y, instanceData);
}
@Override
public boolean isWalkable() {
return WALKABLE;
}
@Override
public int getMovementCost() {
return MOVEMENT_COST;
}
}
// 具体享元类 - 水域地形
class WaterTerrain implements Terrain {
private static final String TYPE = "Water";
private static final boolean WALKABLE = false;
private static final int MOVEMENT_COST = Integer.MAX_VALUE;
@Override
public void render(int x, int y, String instanceData) {
System.out.printf("渲染水域地形在(%d,%d),实例数据:%s%n", x, y, instanceData);
}
@Override
public boolean isWalkable() {
return WALKABLE;
}
@Override
public int getMovementCost() {
return MOVEMENT_COST;
}
}
// 具体享元类 - 山地形
class MountainTerrain implements Terrain {
private static final String TYPE = "Mountain";
private static final boolean WALKABLE = false;
private static final int MOVEMENT_COST = Integer.MAX_VALUE;
@Override
public void render(int x, int y, String instanceData) {
System.out.printf("渲染山地形在(%d,%d),实例数据:%s%n", x, y, instanceData);
}
@Override
public boolean isWalkable() {
return WALKABLE;
}
@Override
public int getMovementCost() {
return MOVEMENT_COST;
}
}
// 具体享元类 - 道路地形
class RoadTerrain implements Terrain {
private static final String TYPE = "Road";
private static final boolean WALKABLE = true;
private static final int MOVEMENT_COST = 1;
@Override
public void render(int x, int y, String instanceData) {
System.out.printf("渲染道路地形在(%d,%d),实例数据:%s%n", x, y, instanceData);
}
@Override
public boolean isWalkable() {
return WALKABLE;
}
@Override
public int getMovementCost() {
return MOVEMENT_COST;
}
}
// 享元工厂
class TerrainFactory {
private static final Map<String, Terrain> terrainTypes = new HashMap<>();
static {
terrainTypes.put("grass", new GrassTerrain());
terrainTypes.put("water", new WaterTerrain());
terrainTypes.put("mountain", new MountainTerrain());
terrainTypes.put("road", new RoadTerrain());
}
public static Terrain getTerrain(String type) {
Terrain terrain = terrainTypes.get(type.toLowerCase());
if (terrain == null) {
throw new IllegalArgumentException("未知的地形类型: " + type);
}
return terrain;
}
public static int getTerrainTypeCount() {
return terrainTypes.size();
}
}
// 地形实例(包含外部状态)
class TerrainTile {
private int x, y;
private Terrain terrain;
private String variation; // 外部状态:地形变种
private boolean hasResource; // 外部状态:是否有资源
public TerrainTile(int x, int y, Terrain terrain, String variation, boolean hasResource) {
this.x = x;
this.y = y;
this.terrain = terrain;
this.variation = variation;
this.hasResource = hasResource;
}
public void render() {
String instanceData = String.format("变种:%s, 资源:%s", variation, hasResource ? "有" : "无");
terrain.render(x, y, instanceData);
}
public boolean isWalkable() {
return terrain.isWalkable();
}
public int getMovementCost() {
return terrain.getMovementCost();
}
// getters
public int getX() { return x; }
public int getY() { return y; }
public String getVariation() { return variation; }
public boolean hasResource() { return hasResource; }
}
// 游戏地图类
class GameMap {
private List<TerrainTile> tiles = new ArrayList<>();
private int width, height;
public GameMap(int width, int height) {
this.width = width;
this.height = height;
}
public void addTile(int x, int y, String terrainType, String variation, boolean hasResource) {
if (x >= 0 && x < width && y >= 0 && y < height) {
Terrain terrain = TerrainFactory.getTerrain(terrainType);
tiles.add(new TerrainTile(x, y, terrain, variation, hasResource));
}
}
public void render() {
System.out.println("=== 渲染游戏地图 ===");
System.out.println("地图大小: " + width + "x" + height);
System.out.println("地形类型数量: " + TerrainFactory.getTerrainTypeCount());
System.out.println("地形实例数量: " + tiles.size());
for (TerrainTile tile : tiles) {
tile.render();
}
}
public List<TerrainTile> getWalkableTiles() {
List<TerrainTile> walkableTiles = new ArrayList<>();
for (TerrainTile tile : tiles) {
if (tile.isWalkable()) {
walkableTiles.add(tile);
}
}
return walkableTiles;
}
}
// 客户端使用示例
public class GameMapDemo {
public static void main(String[] args) {
GameMap gameMap = new GameMap(100, 100);
// 创建大量地形实例,但只有几种地形类型
Random random = new Random();
String[] terrainTypes = {"grass", "water", "mountain", "road"};
String[] variations = {"light", "dark", "normal"};
// 模拟创建一个大地图的地形
for (int i = 0; i < 1000; i++) {
int x = random.nextInt(100);
int y = random.nextInt(100);
String terrainType = terrainTypes[random.nextInt(terrainTypes.length)];
String variation = variations[random.nextInt(variations.length)];
boolean hasResource = random.nextDouble() < 0.1; // 10%概率有资源
gameMap.addTile(x, y, terrainType, variation, hasResource);
}
// 渲染地图
gameMap.render();
// 获取可行走的地形
List<TerrainTile> walkableTiles = gameMap.getWalkableTiles();
System.out.println("\n可行走的地形数量: " + walkableTiles.size());
// 显示前10个可行走地形
System.out.println("\n前10个可行走地形:");
for (int i = 0; i < Math.min(10, walkableTiles.size()); i++) {
TerrainTile tile = walkableTiles.get(i);
System.out.printf("位置(%d,%d), 变种:%s%n",
tile.getX(), tile.getY(), tile.getVariation());
}
}
}
浙公网安备 33010602011771号