【Java】23种设计模式——11.享元模式

概念

享元模式(Flyweight Pattern)‌ 是 ‌GoF 23种设计模式‌ 中的 ‌结构型模式‌,核心思想是 ‌通过共享技术高效支持大量细粒度对象的复用‌,减少内存消耗。适用于系统中存在大量相似对象且对象状态可分离的场景(如字符渲染、游戏粒子系统)。

享元模式的特点

  • 内部状态vs外部状态 内部状态不可变(如颜色),由享元对象存储;外部状态可变(如位置),由客户端传递
  • 对象复用 通过工厂缓存共享对象,避免重复创建

角色

角色 职责
Flyweight‌(抽象化共享对象) 定义共享对象的接口(如 Shape 接口)
ConcreteFlyweight‌(具体共享对象) 实现具体共享对象(如 Circle 类),存储 ‌内部状态‌(不可变部分)
FlyweightFactory‌(共享对象工厂) 管理共享对象的工厂,确保对象复用(如缓存池)
Client‌(共享客户端) 使用享元对象,维护 ‌外部状态‌(可变部分)

适用场景

系统中存在大量相似对象、对象的大部分状态可以外部化

  • 文本编辑器 每个字符的字体、大小作为内部状态共享,位置、颜色作为外部状态传递。
  • 游戏开发 例子系统(如子弹、火焰)复用相同的纹理和模型,仅位置、速度由外部控制。
  • 数据连接池 复用已经建立的连接对象,避免频繁创建和销毁。

使用

  • 抽象化共享对象(享元接口) (形状抽象化)

    /**
     * 抽象化共享对象 : 形状
     * @Author:lyj
     * @Date:2025/5/15 14:29
     */
    public interface Shap {
        /**
         * 绘制形状, x,y为外部状态(由客户端传递)
         * @param x
         * @param y
         */
        public void draw(int x, int y);
    }
    
  • 具体共享对象(享元对象) (圆形、多边形)

    /**
     * 具体享元类 : 圆(内部状态,颜色)
     * @Author:lyj
     * @Date:2025/5/15 14:32
     */
    public class Circle implements Shap {
        private String color;       // 颜色
        public Circle(String color) {
            this.color = color;
        }
    
        @Override
        public void draw(int x, int y) {
            System.out.printf("圆形{颜色:[%s],位置[%d,%d]} ",color ,x,y);
            System.out.println();
        }
    }
    
    
    /**
     * 具体享元类 : 多边形(内部状态,边数量)
     * @Author:lyj
     * @Date:2025/5/15 14:32
     */
    public class Polygon implements Shap {
        private String color;       // 颜色
    
        public Polygon(String color) {
            this.color = color;
        }
    
        @Override
        public void draw(int x, int y) {
            System.out.printf("多边形{颜色[%s],位置[%d,%d]}",color ,x,y);
            System.out.println();
        }
    }
    
  • 共享对象工厂(享元工厂) 获取图形形状、位置

    /**
     * 享元工厂类 : 获取形状对象(颜色、位置)
     * @Author:lyj
     * @Date:2025/5/15 15:26
     */
    public class ShapFactory {
        private static final Map<String, Shap> shapes = new HashMap<>();
    
        /**
         * 获取共享对象(按颜色复用)
         * @param type 类型
         * @param color 颜色
         * @return
         */
        public static Shap getShape(String type, String color)
        {
            String key = type + color;
            Shap shape = shapes.get(key);
            if (shape == null){
                switch (type.toLowerCase()){
                    case "圆形":
                        shape = new Circle(color);
                        break;
                    case "多边形":
                        shape = new Polygon(color);
                        break;
                    default:
                        throw new IllegalArgumentException("不支持形状类型");
    
                }
                shapes.put(key,shape);
            }
            return shape;
    
        }
    
    }
    
  • 共享客户端

    运行结果,详见注释

    // 外部状态(位置)由客户端维护
    int[][] points = {{1,2}, {3,4}, {5,6},{7,8},{9,10},{11,12}};
    // 通过工厂类获取享元对象
    Shap redCircle = ShapFactory.getShape("圆形","红色");
    Shap blueCircle = ShapFactory.getShape("圆形","蓝色");
    Shap yellowCircle = ShapFactory.getShape("圆形","黄色");
    Shap redPolygon = ShapFactory.getShape("多边形","红色");
    Shap bluePolygon = ShapFactory.getShape("多边形","蓝色");
    Shap yellowPolygon = ShapFactory.getShape("多边形","黄色");
    // 绘制图形(传递外部形态)
    redCircle.draw(points[0][0],points[0][1]);  //圆形{颜色:[红色],位置[1,2]} 
    blueCircle.draw(points[1][0],points[1][1]); //圆形{颜色:[蓝色],位置[3,4]}
    yellowCircle.draw(points[2][0],points[2][1]);   //圆形{颜色:[黄色],位置[5,6]}
    redPolygon.draw(points[3][0],points[3][1]); //多边形{颜色:[红色],位置[7,8]}
    bluePolygon.draw(points[4][0],points[4][1]);    //多边形{颜色:[蓝色],位置[9,10]}
    yellowPolygon.draw(points[5][0],points[5][1]);  //多边形{颜色:[黄色],位置[11,12]}
    
posted @ 2025-06-20 16:32  陆陆无为而治者  阅读(54)  评论(0)    收藏  举报