23种设计模式-享元(Flyweight)设计模式

发布于:2025-03-25 ⋅ 阅读:(36) ⋅ 点赞:(0)

🚩什么是享元设计模式?

享元设计模式(Flyweight Pattern) 是一种 结构型设计模式,它通过 共享对象 来有效支持大量细粒度对象的复用。享元模式的核心思想是 分离对象的内部状态和外部状态,通过共享内部状态来减少内存消耗。

使用场景

  • 当系统需要 创建大量相似对象 时,且这些对象的大部分状态可以外部化。

  • 当对象的 创建成本较高(如占用内存大或初始化时间长)时。

  • 当需要 缓存对象 以提高性能时,如游戏中的粒子系统、文字编辑器中的字符对象等。

🚩享元设计模式的特点

  • 共享对象:通过共享相同内部状态的对象来减少内存消耗。

  • 分离状态:将对象状态分为 内部状态(可共享)外部状态(不可共享)

  • 工厂管理:通常使用工厂类来管理和复用享元对象。

  • 性能优化:特别适用于需要创建大量相似对象的场景。

🚩享元设计模式的结构

享元模式主要包含以下部分:

  • Flyweight(抽象享元):定义对象的接口,声明设置外部状态的方法。

  • ConcreteFlyweight(具体享元):实现抽象享元接口,存储内部状态。

  • UnsharedConcreteFlyweight(非共享具体享元):不需要共享的子类。

  • FlyweightFactory(享元工厂):创建和管理享元对象,确保合理地共享享元。

  • Client(客户端):维护外部状态,并在需要时请求享元对象。

🚩享元设计模式的优缺点

✅ 优点

  • 减少内存消耗:通过共享对象显著减少内存使用。

  • 提高性能:减少了创建对象的数量,降低了系统开销。

  • 灵活性:外部状态可以动态变化,不影响共享的内部状态。

❌ 缺点

  • 增加系统复杂度:需要分离内部状态和外部状态。

  • 线程安全问题:共享对象需要考虑线程安全问题。

  • 不适合所有场景:仅当系统中存在大量相似对象时才有效。

🚩享元设计模式的Java实现

代码地址:GitHub

  • 创建 抽象享元 Shape,定义绘制方法。
/**
 * @author hanson.huang
 * @version V1.0
 * @ClassName Shape
 * @Description 抽象享元 Shape
 * @date 2025/3/24 18:23
 **/
public abstract class Shape {

    protected String color; // 内部状态

    public abstract void draw(int x, int y); // 外部状态作为参数
}
  • 创建 具体享元 Circle,实现绘制方法。
/**
 * @author hanson.huang
 * @version V1.0
 * @ClassName Circle
 * @Description 具体享元 Circle
 * @date 2025/3/24 18:24
 **/
public class Circle extends Shape {

    public Circle(String color) {
        this.color = color;
    }

    @Override
    public void draw(int x, int y) {
        System.out.println("draw a color:" + color + " circle x:" + x + " y:" + y);
    }
}
  • 创建 享元工厂 ShapeFactory,管理享元对象。
/**
 * @author hanson.huang
 * @version V1.0
 * @ClassName ShapeFactory
 * @Description 享元工厂 ShapeFactory 管理享元对象
 * @date 2025/3/24 18:24
 **/
public class ShapeFactory {

    private Map<String, Shape> map = new HashMap<>();

    public Shape getShape(String key) {
        if (!map.containsKey(key)) {
            map.put(key, new Circle(key));
            System.out.println("create color:" + key + " circle");
        }
        return map.get(key);
    }
}
  • 测试享元模式
/**
 * @author hanson.huang
 * @version V1.0
 * @ClassName FlyWeightPattern
 * @Description 测试享元模式
 * @date 2025/3/24 18:26
 **/
public class FlyWeightPattern {

    public static void main(String[] args) {
        ShapeFactory factory = new ShapeFactory();
        Random random = new Random();
        String[] colors = {"red", "blue", "green", "white", "black"};

        for (int i = 1; i <= 100; i++) {
            int x = random.nextInt(colors.length);
            Shape shape = factory.getShape(colors[x]);

            System.out.print("第" + i + "个圆:");
            shape.draw(random.nextInt(2025), random.nextInt(324));
        }
    }
}

📌 运行结果(部分)

在这里插入图片描述

🚩代码总结

  • 抽象享元 Shape 定义绘制方法,颜色作为内部状态。

  • 具体享元 Circle 实现绘制方法,存储颜色(内部状态)。

  • 享元工厂 ShapeFactory 管理共享的圆形对象,按颜色复用。

  • 客户端 维护外部状态(坐标),通过工厂获取享元对象。

🚩总结

  • 享元设计模式 通过共享对象减少内存消耗,适合处理大量相似对象。

  • 核心是 分离内部状态(可共享)外部状态(不可共享)

  • 适用于 图形编辑器游戏开发文本处理 等需要创建大量相似对象的场景。

✅ 适用场景:

  • 系统需要创建大量相似对象时

  • 对象的大部分状态可以外部化时

  • 需要优化内存使用和提高性能时

  • Java中很多地方用到了享元设计模式,Integer 类内部有一个缓存机制,使用了享元模式来共享一定范围内的 Integer 对象,以此减少对象的创建数量,节省内存。Integer.valueOf() 方法会优先从缓存中获取 Integer 对象,若缓存中不存在才会创建新对象。再例如,java.lang.String 类的字符串常量池是享元模式的典型应用。当创建字符串对象时,如果字符串常量池中已经存在相同内容的字符串,就会直接返回常量池中的对象,而不是创建新对象。

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

在这里插入图片描述