享元模式屬於結構型模式,核心目標是通過共享技術有效地支持大量細粒度對象,避免大量相似對象的開銷(如內存消耗)。適用於「大量相似對象、狀態可分離」的場景。
getFlyweight(key) 獲取/創建共享對象。場景:數萬張 CD,歌手名大量重複。將「歌手」作為享元共享。
// 1. 內部狀態:歌手(不可變,可共享)
class Artist {
private final String name; // 內部狀態
public Artist(String name) { this.name = name; }
public String getName() { return name; }
}
// 2. 享元工廠:管理歌手池
class ArtistFactory {
private Map pool = new HashMap<>();
public Artist getArtist(String name) {
return pool.computeIfAbsent(name, Artist::new);
}
}
// 3. 外部狀態:CD 標題、年份(不共享)
class CD {
private String title;
private int year;
private Artist artist; // 引用共享歌手
// getter/setter...
}
// 4. 使用
ArtistFactory factory = new ArtistFactory();
CD cd1 = new CD("Album1", 2000, factory.getArtist("Jay Chou"));
CD cd2 = new CD("Album2", 2005, factory.getArtist("Jay Chou")); // 同一 Artist 實例
System.out.println(cd1.getArtist() == cd2.getArtist()); // true,節省內存
解析大量 XML 記錄時,重複字符串(如標籤名、枚舉值)可放入享元池,顯著降低內存佔用,提升解析速度。
| 優點 | 缺點/注意 |
|---|---|
| 大幅減少對象數量,降低內存 | 增加系統複雜度(需分離狀態) |
| 提升性能(減少 GC、提高緩存命中) | 運行時查找/傳遞外部狀態有微小開銷 |
| 內部狀態不可變,天然線程安全 | 適用於「大量相似、狀態可分離」場景,濫用反增複雜度 |
Integer.valueOf(-128~127) 緩存池。String.intern() 字符串常量池。Boolean.valueOf() 只返回兩個實例。享元模式是「空間換時間」的經典體現,大數據、高併發場景下極具價值。