定义
享元模式是一种结构型设计模式,它通过共享技术来高效地支持大量细粒度对象的重用。该模式的核心思想是将对象的状态分为:
内部状态(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()) + " 个对象内存");
}
}