文章目录
-
- 什么是享元模式?
- 核心思想
- 生活中的享元模式
- 模式结构
- 基础示例:文字编辑器
-
- [1. 享元接口和具体享元](#1. 享元接口和具体享元)
- [2. 享元工厂](#2. 享元工厂)
- [3. 客户端使用](#3. 客户端使用)
- [4. 测试客户端](#4. 测试客户端)
- 完整示例:围棋游戏
-
- [1. 围棋棋子享元](#1. 围棋棋子享元)
- [2. 围棋棋盘](#2. 围棋棋盘)
- [3. 游戏客户端](#3. 游戏客户端)
- 实际应用示例:数据库连接池
- 享元模式的优点
-
- [1. 大幅减少内存使用](#1. 大幅减少内存使用)
- [2. 提高性能](#2. 提高性能)
- [3. 更好的对象管理](#3. 更好的对象管理)
- 享元模式的缺点
-
- [1. 增加系统复杂度](#1. 增加系统复杂度)
- [2. 可能引入线程安全问题](#2. 可能引入线程安全问题)
- 适用场景
- 最佳实践
-
- [1. 合理划分内部状态和外部状态](#1. 合理划分内部状态和外部状态)
- [2. 使用工厂管理享元对象](#2. 使用工厂管理享元对象)
- [3. 考虑线程安全性](#3. 考虑线程安全性)
- [享元模式 vs 其他模式](#享元模式 vs 其他模式)
- 总结
什么是享元模式?
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享技术来有效地支持大量细粒度对象的复用。享元模式通过共享已经存在的对象来减少内存使用,提高系统性能。
核心思想
享元模式的核心思想是:将对象的属性分为内部状态和外部状态,内部状态可以共享,外部状态由客户端维护,从而减少内存中对象的数量。
生活中的享元模式
想象一下字处理软件:
- 每个字符都有字体、大小、颜色等属性
- 如果每个字符都存储所有属性,内存会爆炸
- 实际上,相同格式的字符共享格式信息
- 只有字符内容和位置是每个字符独有的
这就是享元模式的思想!
模式结构
享元模式包含四个核心角色:
- 享元接口(Flyweight):定义享元对象的接口
- 具体享元(ConcreteFlyweight):实现享元接口,包含内部状态
- 享元工厂(FlyweightFactory):创建和管理享元对象
- 客户端(Client):维护外部状态,使用享元对象
基础示例:文字编辑器
1. 享元接口和具体享元
java
/**
* 字符享元接口
*/
public interface CharacterFlyweight {
/**
* 显示字符
* @param externalState 外部状态(位置、颜色等)
*/
void display(CharacterExternalState externalState);
/**
* 获取字符内容
*/
char getCharacter();
/**
* 获取内部状态
*/
CharacterInternalState getInternalState();
}
/**
* 字符内部状态 - 可以共享的部分
*/
class CharacterInternalState {
private final String fontFamily;
private final int fontSize;
private final boolean isBold;
private final boolean isItalic;
public CharacterInternalState(String fontFamily, int fontSize,
boolean isBold, boolean isItalic) {
this.fontFamily = fontFamily;
this.fontSize = fontSize;
this.isBold = isBold;
this.isItalic = isItalic;
}
// Getter方法
public String getFontFamily() { return fontFamily; }
public int getFontSize() { return fontSize; }
public boolean isBold() { return isBold; }
public boolean isItalic() { return isItalic; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CharacterInternalState that = (CharacterInternalState) o;
return fontSize == that.fontSize &&
isBold == that.isBold &&
isItalic == that.isItalic &&
Objects.equals(fontFamily, that.fontFamily);
}
@Override
public int hashCode() {
return Objects.hash(fontFamily, fontSize, isBold, isItalic);
}
@Override
public String toString() {
return String.format("字体:%s, 大小:%d, 粗体:%s, 斜体:%s",
fontFamily, fontSize, isBold ? "是" : "否", isItalic ? "是" : "否");
}
}
/**
* 字符外部状态 - 不可共享的部分
*/
class CharacterExternalState {
private final int positionX;
private final int positionY;
private final String color;
public CharacterExternalState(int positionX, int positionY, String color) {
this.positionX = positionX;
this.positionY = positionY;
this.color = color;
}
// Getter方法
public int getPositionX() { return positionX; }
public int getPositionY() { return positionY; }
public String getColor() { return color; }
@Override
public String toString() {
return String.format("位置(%d,%d), 颜色:%s", positionX, positionY, color);
}
}
/**
* 具体字符享元
*/
public class ConcreteCharacter implements CharacterFlyweight {
private final char character;
private final CharacterInternalState internalState;
public ConcreteCharacter(char character, CharacterInternalState internalState) {
this.character = character;
this.internalState = internalState;
}
@Override
public void display(CharacterExternalState externalState) {
System.out.printf("字符 '%c' [%s] [%s]%n",
character, internalState, externalState);
}
@Override
public char getCharacter() {
return character;
}
@Override
public CharacterInternalState getInternalState() {
return internalState;
}
}
2. 享元工厂
java
import java.util.HashMap;
import java.util.Map;
/**
* 字符享元工厂
* 管理字符享元对象的创建和共享
*/
public class CharacterFlyweightFactory {
private static CharacterFlyweightFactory instance;
private final Map<String, CharacterFlyweight> characterPool;
private CharacterFlyweightFactory() {
this.characterPool = new HashMap<>();
}
public static CharacterFlyweightFactory getInstance() {
if (instance == null) {
instance = new CharacterFlyweightFactory();
}
return instance;
}
/**
* 获取字符享元对象
*/
public CharacterFlyweight getCharacter(char character, CharacterInternalState internalState) {
String key = generateKey(character, internalState);
// 如果池中已存在,直接返回
if (characterPool.containsKey(key)) {
System.out.printf("✓ 共享字符: '%c' [%s]%n", character, internalState);
return characterPool.get(key);
}
// 否则创建新的享元对象并放入池中
System.out.printf("➤ 创建新字符: '%c' [%s]%n", character, internalState);
CharacterFlyweight flyweight = new ConcreteCharacter(character, internalState);
characterPool.put(key, flyweight);
return flyweight;
}
/**
* 生成享元对象的键
*/
private String generateKey(char character, CharacterInternalState internalState) {
return character + "|" + internalState.hashCode();
}
/**
* 获取池中享元对象数量
*/
public int getPoolSize() {
return characterPool.size();
}
/**
* 显示池中所有享元对象
*/
public void displayPool() {
System.out.println("\n📊 字符享元池内容:");
System.out.println("-".repeat(50));
characterPool.forEach((key, flyweight) -> {
ConcreteCharacter character = (ConcreteCharacter) flyweight;
System.out.printf("键: %s -> 字符: '%c' [%s]%n",
key, character.getCharacter(), character.getInternalState());
});
System.out.println("总计: " + characterPool.size() + " 个享元对象");
}
}
3. 客户端使用
java
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 文档编辑器 - 客户端
*/
public class DocumentEditor {
private final List<CharacterContext> documentContent;
private final CharacterFlyweightFactory factory;
private final Random random;
public DocumentEditor() {
this.documentContent = new ArrayList<>();
this.factory = CharacterFlyweightFactory.getInstance();
this.random = new Random();
}
/**
* 向文档添加字符
*/
public void addCharacter(char character, CharacterInternalState internalState,
int positionX, int positionY, String color) {
// 获取享元对象
CharacterFlyweight flyweight = factory.getCharacter(character, internalState);
// 创建外部状态
CharacterExternalState externalState = new CharacterExternalState(positionX, positionY, color);
// 保存字符上下文
CharacterContext context = new CharacterContext(flyweight, externalState);
documentContent.add(context);
}
/**
* 显示文档内容
*/
public void displayDocument() {
System.out.println("\n📄 文档内容:");
System.out.println("=" .repeat(60));
for (CharacterContext context : documentContent) {
context.display();
}
System.out.println("=" .repeat(60));
System.out.printf("文档字符数: %d, 享元对象数: %d, 节省内存: %.1f%%%n",
documentContent.size(), factory.getPoolSize(),
(1 - (double) factory.getPoolSize() / documentContent.size()) * 100);
}
/**
* 生成测试文档
*/
public void generateTestDocument() {
System.out.println("🛠️ 生成测试文档...");
// 定义几种格式
CharacterInternalState[] formats = {
new CharacterInternalState("宋体", 12, false, false), // 普通文本
new CharacterInternalState("黑体", 14, true, false), // 标题
new CharacterInternalState("楷体", 12, false, true), // 强调
new CharacterInternalState("宋体", 10, false, false) // 小字
};
String[] colors = {"黑色", "红色", "蓝色", "绿色"};
String text = "享元模式通过共享技术来有效地支持大量细粒度对象的复用";
int position = 0;
for (char c : text.toCharArray()) {
// 随机选择格式和颜色
CharacterInternalState format = formats[random.nextInt(formats.length)];
String color = colors[random.nextInt(colors.length)];
addCharacter(c, format, position * 20, 0, color);
position++;
}
}
}
/**
* 字符上下文 - 维护外部状态
*/
class CharacterContext {
private final CharacterFlyweight flyweight;
private final CharacterExternalState externalState;
public CharacterContext(CharacterFlyweight flyweight, CharacterExternalState externalState) {
this.flyweight = flyweight;
this.externalState = externalState;
}
public void display() {
flyweight.display(externalState);
}
public CharacterFlyweight getFlyweight() {
return flyweight;
}
public CharacterExternalState getExternalState() {
return externalState;
}
}
4. 测试客户端
java
/**
* 享元模式测试客户端
*/
public class FlyweightClient {
public static void main(String[] args) {
System.out.println("=== 享元模式演示 - 文字编辑器 ===\n");
DocumentEditor editor = new DocumentEditor();
// 演示1:基础使用
demonstrateBasicUsage(editor);
// 演示2:性能对比
demonstratePerformanceComparison();
// 演示3:实际应用场景
demonstrateRealWorldScenario();
}
/**
* 演示基础使用
*/
private static void demonstrateBasicUsage(DocumentEditor editor) {
System.out.println("1. 基础使用演示:");
System.out.println("-".repeat(50));
// 创建几种格式
CharacterInternalState normal = new CharacterInternalState("宋体", 12, false, false);
CharacterInternalState bold = new CharacterInternalState("黑体", 14, true, false);
CharacterInternalState italic = new CharacterInternalState("楷体", 12, false, true);
// 添加一些字符
editor.addCharacter('H', bold, 0, 0, "红色");
editor.addCharacter('e', normal, 20, 0, "黑色");
editor.addCharacter('l', normal, 40, 0, "黑色");
editor.addCharacter('l', normal, 60, 0, "黑色"); // 重复字符,应该共享
editor.addCharacter('o', italic, 80, 0, "蓝色");
editor.addCharacter('!', bold, 100, 0, "红色");
// 显示文档
editor.displayDocument();
// 显示享元池
CharacterFlyweightFactory.getInstance().displayPool();
}
/**
* 演示性能对比
*/
private static void demonstratePerformanceComparison() {
System.out.println("\n2. 性能对比演示:");
System.out.println("-".repeat(50));
// 测试不使用享元模式
long startTime = System.currentTimeMillis();
testWithoutFlyweight();
long withoutFlyweightTime = System.currentTimeMillis() - startTime;
// 测试使用享元模式
startTime = System.currentTimeMillis();
testWithFlyweight();
long withFlyweightTime = System.currentTimeMillis() - startTime;
System.out.println("\n⏱️ 性能对比结果:");
System.out.printf("不使用享元模式: %d ms%n", withoutFlyweightTime);
System.out.printf("使用享元模式: %d ms%n", withFlyweightTime);
System.out.printf("性能提升: %.1f%%%n",
(1 - (double) withFlyweightTime / withoutFlyweightTime) * 100);
}
private static void testWithoutFlyweight() {
List<SimpleCharacter> characters = new ArrayList<>();
CharacterInternalState format = new CharacterInternalState("宋体", 12, false, false);
// 创建10000个字符对象
for (int i = 0; i < 10000; i++) {
char c = (char) ('A' + (i % 26));
characters.add(new SimpleCharacter(c, format, i * 10, 0, "黑色"));
}
}
private static void testWithFlyweight() {
DocumentEditor editor = new DocumentEditor();
CharacterInternalState format = new CharacterInternalState("宋体", 12, false, false);
// 创建10000个字符,但共享享元对象
for (int i = 0; i < 10000; i++) {
char c = (char) ('A' + (i % 26));
editor.addCharacter(c, format, i * 10, 0, "黑色");
}
}
/**
* 演示实际应用场景
*/
private static void demonstrateRealWorldScenario() {
System.out.println("\n3. 实际应用场景演示:");
System.out.println("-".repeat(50));
DocumentEditor editor = new DocumentEditor();
editor.generateTestDocument();
editor.displayDocument();
CharacterFlyweightFactory.getInstance().displayPool();
}
}
/**
* 简单字符类 - 用于对比测试
*/
class SimpleCharacter {
private char character;
private CharacterInternalState internalState;
private int positionX;
private int positionY;
private String color;
public SimpleCharacter(char character, CharacterInternalState internalState,
int positionX, int positionY, String color) {
this.character = character;
this.internalState = internalState;
this.positionX = positionX;
this.positionY = positionY;
this.color = color;
}
}
完整示例:围棋游戏
让我们通过一个更复杂的围棋游戏示例来深入理解享元模式。
1. 围棋棋子享元
java
import java.util.HashMap;
import java.util.Map;
/**
* 围棋棋子享元接口
*/
public interface GoPiece {
/**
* 显示棋子
* @param externalState 外部状态(位置)
*/
void display(PieceExternalState externalState);
/**
* 获取棋子颜色
*/
String getColor();
}
/**
* 棋子内部状态
*/
class PieceInternalState {
private final String color; // 颜色是内部状态,可以共享
private final String shape; // 形状(圆形)
public PieceInternalState(String color) {
this.color = color;
this.shape = "圆形";
}
public String getColor() { return color; }
public String getShape() { return shape; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
PieceInternalState that = (PieceInternalState) o;
return Objects.equals(color, that.color) &&
Objects.equals(shape, that.shape);
}
@Override
public int hashCode() {
return Objects.hash(color, shape);
}
@Override
public String toString() {
return color + shape;
}
}
/**
* 棋子外部状态
*/
class PieceExternalState {
private final int x;
private final int y;
public PieceExternalState(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() { return x; }
public int getY() { return y; }
@Override
public String toString() {
return String.format("位置(%d,%d)", x, y);
}
}
/**
* 具体围棋棋子
*/
class ConcreteGoPiece implements GoPiece {
private final PieceInternalState internalState;
public ConcreteGoPiece(PieceInternalState internalState) {
this.internalState = internalState;
}
@Override
public void display(PieceExternalState externalState) {
System.out.printf("○ %s棋子 %s%n", internalState.getColor(), externalState);
}
@Override
public String getColor() {
return internalState.getColor();
}
public PieceInternalState getInternalState() {
return internalState;
}
}
/**
* 围棋棋子工厂
*/
class GoPieceFactory {
private static GoPieceFactory instance;
private final Map<String, GoPiece> piecePool;
private GoPieceFactory() {
this.piecePool = new HashMap<>();
}
public static GoPieceFactory getInstance() {
if (instance == null) {
instance = new GoPieceFactory();
}
return instance;
}
public GoPiece getPiece(String color) {
// 如果池中已存在,直接返回
if (piecePool.containsKey(color)) {
System.out.printf("✓ 共享%s棋子%n", color);
return piecePool.get(color);
}
// 否则创建新的享元对象
System.out.printf("➤ 创建新%s棋子%n", color);
PieceInternalState internalState = new PieceInternalState(color);
GoPiece piece = new ConcreteGoPiece(internalState);
piecePool.put(color, piece);
return piece;
}
public int getPoolSize() {
return piecePool.size();
}
public void displayPool() {
System.out.println("\n🎲 棋子享元池:");
piecePool.forEach((color, piece) -> {
System.out.printf("颜色: %s -> %s%n", color, piece.getColor());
});
System.out.println("总计: " + piecePool.size() + " 种棋子");
}
}
2. 围棋棋盘
java
import java.util.ArrayList;
import java.util.List;
/**
* 围棋棋盘
*/
public class GoBoard {
private final List<PieceContext> pieces;
private final GoPieceFactory factory;
private static final int BOARD_SIZE = 19;
public GoBoard() {
this.pieces = new ArrayList<>();
this.factory = GoPieceFactory.getInstance();
}
/**
* 在棋盘上放置棋子
*/
public void placePiece(String color, int x, int y) {
if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE) {
System.out.println("❌ 无效位置: (" + x + "," + y + ")");
return;
}
// 检查位置是否已有棋子
if (hasPieceAt(x, y)) {
System.out.println("❌ 位置 (" + x + "," + y + ") 已有棋子");
return;
}
// 获取棋子享元
GoPiece piece = factory.getPiece(color);
// 创建外部状态
PieceExternalState externalState = new PieceExternalState(x, y);
// 保存棋子上下文
PieceContext context = new PieceContext(piece, externalState);
pieces.add(context);
System.out.printf("✅ 在(%d,%d)放置%s棋子%n", x, y, color);
}
/**
* 检查位置是否有棋子
*/
private boolean hasPieceAt(int x, int y) {
return pieces.stream().anyMatch(context ->
context.getExternalState().getX() == x &&
context.getExternalState().getY() == y);
}
/**
* 显示棋盘状态
*/
public void displayBoard() {
System.out.println("\n🎯 棋盘状态:");
System.out.println("=" .repeat(40));
for (PieceContext context : pieces) {
context.display();
}
System.out.println("=" .repeat(40));
System.out.printf("棋盘棋子数: %d, 享元对象数: %d%n",
pieces.size(), factory.getPoolSize());
}
/**
* 模拟一局围棋
*/
public void simulateGame() {
System.out.println("🎮 开始模拟围棋对局...");
// 黑棋先行
placePiece("黑", 3, 3);
placePiece("黑", 4, 4);
placePiece("黑", 5, 5);
// 白棋应对
placePiece("白", 3, 4);
placePiece("白", 4, 3);
placePiece("白", 5, 4);
// 继续对局
placePiece("黑", 6, 6);
placePiece("白", 6, 5);
placePiece("黑", 7, 7);
placePiece("白", 7, 6);
// 尝试在已有位置放置棋子
placePiece("黑", 3, 3); // 应该失败
System.out.println("\n对局结束!");
}
}
/**
* 棋子上下文
*/
class PieceContext {
private final GoPiece piece;
private final PieceExternalState externalState;
public PieceContext(GoPiece piece, PieceExternalState externalState) {
this.piece = piece;
this.externalState = externalState;
}
public void display() {
piece.display(externalState);
}
public GoPiece getPiece() {
return piece;
}
public PieceExternalState getExternalState() {
return externalState;
}
}
3. 游戏客户端
java
/**
* 围棋游戏客户端
*/
public class GoGameClient {
public static void main(String[] args) {
System.out.println("=== 享元模式演示 - 围棋游戏 ===\n");
GoBoard board = new GoBoard();
// 演示围棋游戏
board.simulateGame();
board.displayBoard();
// 显示享元池
GoPieceFactory.getInstance().displayPool();
// 演示内存节省
demonstrateMemorySaving();
}
/**
* 演示内存节省效果
*/
private static void demonstrateMemorySaving() {
System.out.println("\n💾 内存节省演示:");
System.out.println("-".repeat(40));
int totalPieces = 1000;
GoPieceFactory factory = GoPieceFactory.getInstance();
System.out.println("模拟放置 " + totalPieces + " 个棋子:");
// 重置工厂
// 在实际应用中,我们不会这样重置,这里只是为了演示
System.out.println("创建黑白两种棋子享元...");
// 模拟大量棋子放置
GoPiece blackPiece = factory.getPiece("黑");
GoPiece whitePiece = factory.getPiece("白");
System.out.printf("实际创建的享元对象: %d 个%n", factory.getPoolSize());
System.out.printf("内存节省: %d 个对象 -> %d 个享元, 节省 %.1f%% 内存%n",
totalPieces, factory.getPoolSize(),
(1 - (double) factory.getPoolSize() / totalPieces) * 100);
}
}
实际应用示例:数据库连接池
java
import java.util.HashMap;
import java.util.Map;
/**
* 数据库连接池 - 享元模式实际应用
*/
public class ConnectionPool {
private static ConnectionPool instance;
private final Map<String, DatabaseConnection> connectionPool;
private final int maxPoolSize;
private ConnectionPool(int maxPoolSize) {
this.connectionPool = new HashMap<>();
this.maxPoolSize = maxPoolSize;
System.out.println("初始化数据库连接池,最大连接数: " + maxPoolSize);
}
public static ConnectionPool getInstance(int maxPoolSize) {
if (instance == null) {
instance = new ConnectionPool(maxPoolSize);
}
return instance;
}
/**
* 获取数据库连接
*/
public DatabaseConnection getConnection(String databaseUrl, String username) {
String key = databaseUrl + "|" + username;
// 如果连接已存在且可用,直接返回
if (connectionPool.containsKey(key) && connectionPool.get(key).isAvailable()) {
System.out.println("✓ 复用数据库连接: " + key);
return connectionPool.get(key);
}
// 如果连接池已满,等待或抛出异常
if (connectionPool.size() >= maxPoolSize) {
System.out.println("❌ 连接池已满,无法创建新连接");
return null;
}
// 创建新连接
System.out.println("➤ 创建新数据库连接: " + key);
DatabaseConnection connection = new DatabaseConnection(databaseUrl, username);
connectionPool.put(key, connection);
return connection;
}
/**
* 获取连接池状态
*/
public void displayPoolStatus() {
System.out.println("\n📊 连接池状态:");
System.out.println("当前连接数: " + connectionPool.size());
System.out.println("最大连接数: " + maxPoolSize);
System.out.println("使用率: " + (connectionPool.size() * 100 / maxPoolSize) + "%");
}
}
/**
* 数据库连接 - 享元对象
*/
class DatabaseConnection {
private final String databaseUrl;
private final String username;
private boolean inUse;
public DatabaseConnection(String databaseUrl, String username) {
this.databaseUrl = databaseUrl;
this.username = username;
this.inUse = false;
System.out.println("建立到 " + databaseUrl + " 的连接,用户: " + username);
}
public void executeQuery(String sql) {
if (!inUse) {
inUse = true;
System.out.println("执行查询: " + sql);
// 模拟查询执行
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
inUse = false;
} else {
System.out.println("连接正在使用中,无法执行查询");
}
}
public boolean isAvailable() {
return !inUse;
}
public String getConnectionInfo() {
return databaseUrl + " (" + username + ")";
}
}
享元模式的优点
1. 大幅减少内存使用
java
// 没有享元模式:创建1000个独立对象
// 使用享元模式:只创建2个享元对象(黑白棋子)
// 内存节省:998个对象!
2. 提高性能
java
// 对象创建和垃圾回收开销大大减少
// 特别适合大量细粒度对象的场景
3. 更好的对象管理
java
// 通过工厂统一管理享元对象
// 可以轻松实现对象池等功能
享元模式的缺点
1. 增加系统复杂度
java
// 需要区分内部状态和外部状态
// 增加了设计和实现的难度
2. 可能引入线程安全问题
java
// 如果享元对象有状态,需要考虑线程安全
// 外部状态需要由客户端正确管理
适用场景
- 系统中有大量相似对象时
- 对象的大部分状态可以外部化时
- 需要缓冲池的场景
- 需要实现对象共享的场景
最佳实践
1. 合理划分内部状态和外部状态
java
// 内部状态:不变的、可共享的
// 外部状态:变化的、不可共享的
2. 使用工厂管理享元对象
java
public class FlyweightFactory {
// 统一管理享元对象的创建和获取
// 确保对象的正确共享
}
3. 考虑线程安全性
java
// 如果享元对象有状态变化,需要同步控制
public synchronized Flyweight getFlyweight(String key) {
// 线程安全的获取方式
}
享元模式 vs 其他模式
| 模式 | 目的 | 特点 |
|---|---|---|
| 享元模式 | 对象共享 | 减少内存使用,提高性能 |
| 单例模式 | 唯一实例 | 确保一个类只有一个实例 |
| 原型模式 | 对象复制 | 通过复制现有对象创建新对象 |
总结
享元模式就像是"资源共享中心",让相同的资源可以被多次使用,避免重复创建。
核心价值:
- 大幅减少内存中对象的数量
- 提高系统性能
- 更好地管理相似对象
使用场景:
- 系统中有大量相似对象时
- 对象创建开销很大时
- 需要实现对象池功能时
简单记忆:
大量对象不用愁,享元模式来帮忙!
内部状态可共享,外部状态客户端扛。
掌握享元模式,能够让你在处理大量相似对象时游刃有余,显著提升系统性能!