1. 什么是享元模式?

享元模式(Flyweight Pattern) 是一种结构型设计模式,用于高效共享大量细粒度对象,从而减少内存消耗。它通过分离对象的状态为内部状态(Intrinsic)和外部状态(Extrinsic),使得多个对象可以共享相同的内部状态,而外部状态则在使用时动态传入。

2. 核心思想

  • 内部状态(Intrinsic State):对象的共享部分,不会随环境变化,可以在多个上下文中重复使用。
  • 外部状态(Extrinsic State):对象的非共享部分,依赖于具体使用场景,由外部传入。

3. 适用场景

  • 系统中存在大量相似对象,且这些对象的状态可以分解为内部和外部状态。
  • 对象的创建和销毁成本较高,而共享对象能显著降低资源消耗。
  • 典型场景:文本编辑器中的字符、游戏中的角色、图形绘制中的颜色对象等。

Java 实现样例

示例:棋子共享工厂

假设我们要设计一个国际象棋游戏,棋子(如“白棋”和“黑棋”)的颜色是内部状态,而位置是外部状态。通过享元模式,我们可以复用相同颜色的棋子对象。


1. 定义享元接口(Flyweight)
// 棋子接口
public interface ChessPiece {
    void display(Position position);
}

2. 具体享元类(ConcreteFlyweight)
// 棋子具体实现类
public class ChessPieceImpl implements ChessPiece {
    // 内部状态:颜色(共享)
    private final String color;

    public ChessPieceImpl(String color) {
        this.color = color;
        System.out.println("创建棋子: " + color);
    }

    @Override
    public void display(Position position) {
        System.out.println("棋子颜色: " + color + ", 位置: (" + position.getX() + ", " + position.getY() + ")");
    }
}

3. 外部状态类(Extrinsic State)
// 棋子位置(外部状态)
public class Position {
    private final int x;
    private final int y;

    public Position(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

4. 享元工厂(FlyweightFactory)
// 棋子工厂:管理共享对象
public class ChessPieceFactory {
    // 使用 HashMap 缓存已创建的棋子
    private static final Map<String, ChessPiece> POOL = new HashMap<>();

    public static ChessPiece getChessPiece(String color) {
        ChessPiece piece = POOL.get(color);
        if (piece == null) {
            piece = new ChessPieceImpl(color);
            POOL.put(color, piece);
        }
        return piece;
    }

    public static int getCreatedCount() {
        return POOL.size();
    }
}

5. 客户端代码(Client)
public class Client {
    public static void main(String[] args) {
        // 创建多个棋子
        ChessPiece white1 = ChessPieceFactory.getChessPiece("White");
        ChessPiece white2 = ChessPieceFactory.getChessPiece("White");
        ChessPiece black = ChessPieceFactory.getChessPiece("Black");

        // 验证共享:white1 和 white2 是同一个对象
        System.out.println("white1 == white2? " + (white1 == white2)); // 输出 true

        // 显示不同位置的棋子
        white1.display(new Position(1, 2));
        black.display(new Position(3, 4));
        white2.display(new Position(5, 6));
    }
}

6. 输出结果
创建棋子: White
创建棋子: Black
white1 == white2? true
棋子颜色: White, 位置: (1, 2)
棋子颜色: Black, 位置: (3, 4)
棋子颜色: White, 位置: (5, 6)

关键点总结

项目 描述
内部状态 color 字段:所有相同颜色的棋子共享该实例。
外部状态 Position 对象:每次调用 display() 时动态传入。
工厂作用 控制对象创建,确保相同颜色的棋子只创建一次。
优点 节省内存,避免重复创建对象;提高性能。
缺点 增加系统复杂度;需要区分内外状态,维护成本较高。
适用场景 大量细粒度对象存在相似性,且对象创建成本较高时。


应用扩展

  • 文本编辑器:字符对象(如 Character)可共享,字体、颜色等作为外部状态。
  • 游戏开发:子弹、敌人等对象可通过享元模式减少内存占用。
  • Web 服务:共享连接池中的数据库连接对象。

通过合理使用享元模式,可以在保证系统性能的同时,降低资源消耗。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐