设计模式之享元模式

发布于:2025-07-02 ⋅ 阅读:(23) ⋅ 点赞:(0)

定义

       享元模式‌是一种结构型设计模式,它通过共享技术来高效地支持大量细粒度对象的重用。该模式的核心思想是将对象的状态分为:
‌       内部状态(intrinsic)‌: 可共享的部分,存储在享元对象内部。
       ‌外部状态(extrinsic)‌: 不可共享的部分,由客户端在使用时传入。

结构

在这里插入图片描述

适用场景

       1)系统中存在大量相似对象
       2)对象的大部分状态可以外部化
       3)‌需要缓存可共享对象
       4)‌图形渲染、文字处理等内存敏感场景

使用示例

电商SKU商品渲染系统
假设电商平台需要渲染海量商品卡片(如10,000个SKU),每个商品都有:
       1)‌可共享状态‌(内部状态):商品图片、描述、规格
       2)‌不可共享状态‌(外部状态):价格、库存、用户个性化标签
定义享元接口

/**
 * 享元接口:商品数据抽象
 */
public interface ProductFlyweight {

    void render(ProductContext context);

}

定义内部状态(可共享部分)


/**
 * 具体享元:商品基础信息(可共享)
 */
public class ConcreteProduct implements ProductFlyweight {

    private final String sku;

    private final String name;

    private final String imageUrl;

    private final String description;

    public ConcreteProduct(String sku, String name, String imageUrl, String description) {
        this.sku = sku;
        this.name = name;
        this.imageUrl = imageUrl;
        this.description = description;
    }

    @Override
    public void render(ProductContext context) {
        System.out.println("渲染商品卡片: " + name);
        System.out.println("├─ 图片: " + imageUrl);
        System.out.println("├─ 描述: " + description);
        System.out.println("├─ 价格: ¥" + context.getPrice());
        System.out.println("├─ 库存: " + context.getStock() + "件");
        System.out.println("└─ 标签: " + context.getUserTag());
        System.out.println("--------------");
    }
}

定义外部状态(不可共享的部分)

/**
 * 外部状态:价格、库存等个性化数据
 */
public class ProductContext {

    private double price;

    private int stock;

    private String userTag; // 如"新品""限时折扣"

    public ProductContext(double price, int stock, String userTag) {
        this.price = price;
        this.stock = stock;
        this.userTag = userTag;
    }

    // Getters...
    public double getPrice() {
        return price;
    }

    public int getStock() {
        return stock;
    }

    public String getUserTag() {
        return userTag;
    }
}

定义享元工厂

/**
 * 享元工厂:缓存和复用商品基础信息
 */
public class ProductFactory {

    private static final Map<String, ProductFlyweight> products = new HashMap<>();

    public static ProductFlyweight getProduct(String sku, String name,
                                              String imageUrl, String description) {
        String key = sku + "-" + name.hashCode();
        return products.computeIfAbsent(key,
                k -> new ConcreteProduct(sku, name, imageUrl, description));
    }

    public static int getCacheSize() {
        return products.size();
    }
}

测试

/**
 * 客户端:电商页面渲染器
 */
public class Client {

    public static void main(String[] args) {
        // 模拟渲染5个商品(实际可能是数千个)
        for (int i = 1; i <= 5; i++) {
            int realProductNum = (i % 2);
            // 获取享元对象(共享基础信息)
            ProductFlyweight product = ProductFactory.getProduct(
                    "SKU-100" + realProductNum,
                    "商品" + realProductNum,
                    "https://cdn.com/product" + realProductNum + ".jpg",
                    "高品质商品" + realProductNum
            );

            // 创建外部状态(动态数据)
            ProductContext context = new ProductContext(
                    99.9 + i, // 价格
                    100 - i,  // 库存
                    (i % 3 == 0) ? "新品" : (i % 5 == 0) ? "限时折扣" : "" // 标签
            );

            // 渲染商品卡片
            product.render(context);
        }

        System.out.println("实际创建的享元对象数量: " + ProductFactory.getCacheSize());
        System.out.println("内存节省: " + (5 - ProductFactory.getCacheSize()) + " 个对象内存");
    }

}

网站公告

今日签到

点亮在社区的每一天
去签到