设计模式-享源模式

什么是享元模式?

享元模式是一种结构型设计模式,它通过共享技术来有效地支持大量细粒度的对象。享元模式通过共享已经存在的对象来减少创建对象的数量,从而减少内存占用和提高性能。
享元模式包含以下角色:

  • 享元接口(Flyweight):声明一个接口,通过它可以接受并作用于外部状态
  • 具体享元类(ConcreteFlyweight):实现享元接口,并为内部状态增加存储空间
  • 非共享具体享元类(UnsharedConcreteFlyweight):不需要共享的Flyweight子类
  • 享元工厂(FlyweightFactory):创建并管理flyweight对象,确保合理地共享flyweight

享元模式的优缺点

优点:

  • 减少内存使用:通过共享对象,大量减少对象的创建,节省内存空间
  • 提高性能:减少对象创建和垃圾回收的开销
  • 系统资源优化:有效利用系统资源,提高系统整体性能
    缺点:
  • 增加复杂性:需要区分内部状态和外部状态,增加了系统复杂性
  • 线程安全问题:共享对象可能带来线程安全问题,需要额外处理
  • 状态管理复杂:需要仔细管理对象的内部状态和外部状态

什么场景下使用享元模式

  1. 系统中有大量相似对象
  2. 这些对象的大部分状态都可以外部化
  3. 按照内部状态分成很多组,当把对象作为组来处理时,同一组的对象可以被共享
  4. 需要缓冲池的场景
  5. 对象创建开销大,但可以共享的场景

代码举例

// 享元接口 - 地形类型
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());
        }
    }
}

posted @ 2025-09-12 12:39  MaC-Matthew  阅读(10)  评论(0)    收藏  举报