Java享元模式
享元模式通过共享对象减少内存消耗,适用于大量相似对象。
模式定义
意图:运用共享技术有效支持大量细粒度对象。
核心概念
内部状态
可共享的状态,存储在享元对象内部,不随环境改变。
外部状态
不可共享的状态,由客户端保存,使用时传入享元对象。
模式结构
享元接口
Java
public interface Flyweight {
void operation(String externalState);
}
具体享元
Java
public class ConcreteFlyweight implements Flyweight {
private String internalState; // 内部状态
public ConcreteFlyweight(String internalState) {
this.internalState = internalState;
}
@Override
public void operation(String externalState) {
System.out.println("内部状态: " + internalState +
", 外部状态: " + externalState);
}
}
享元工厂
Java
public class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
Flyweight flyweight = flyweights.get(key);
if (flyweight == null) {
flyweight = new ConcreteFlyweight(key);
flyweights.put(key, flyweight);
System.out.println("创建新享元: " + key);
}
return flyweight;
}
public int getFlyweightCount() {
return flyweights.size();
}
}
使用示例
Java
FlyweightFactory factory = new FlyweightFactory();
// 共享相同内部状态的享元
Flyweight f1 = factory.getFlyweight("A"); // 创建
Flyweight f2 = factory.getFlyweight("A"); // 复用
Flyweight f3 = factory.getFlyweight("B"); // 创建
f1.operation("状态1");
f2.operation("状态2");
f3.operation("状态3");
System.out.println("享元数量: " + factory.getFlyweightCount()); // 2
实际应用示例
棋子对象
Java
public interface ChessPiece {
void display(int x, int y);
}
public class ConcreteChess implements ChessPiece {
private String color; // 内部状态(共享)
private String type; // 内部状态(共享)
public ConcreteChess(String color, String type) {
this.color = color;
this.type = type;
}
@Override
public void display(int x, int y) { // x、y是外部状态
System.out.println(color + " " + type + " 在位置(" + x + "," + y + ")");
}
}
public class ChessFactory {
private Map<String, ChessPiece> pieces = new HashMap<>();
public ChessPiece getChess(String color, String type) {
String key = color + "_" + type;
ChessPiece piece = pieces.get(key);
if (piece == null) {
piece = new ConcreteChess(color, type);
pieces.put(key, piece);
}
return piece;
}
}
// 使用
ChessFactory factory = new ChessFactory();
ChessPiece blackKing = factory.getChess("黑", "将");
ChessPiece redKing = factory.getChess("红", "将");
// 同颜色同类型的棋子共享,位置不同
blackKing.display(1, 1);
blackKing.display(2, 3); // 同一个对象,不同位置
Java中的享元
Integer缓存
Java
Integer a = Integer.valueOf(127);
Integer b = Integer.valueOf(127);
System.out.println(a == b); // true,-128到127被缓存
Integer c = Integer.valueOf(128);
Integer d = Integer.valueOf(128);
System.out.println(c == d); // false,超出缓存范围
String常量池
Java
String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true,字符串常量池共享
享元模式优点
- 减少对象数量,节省内存
- 减少创建开销,提高性能
- 外部状态独立,不影响内部
享元模式缺点
- 分离内外状态增加复杂度
- 需维护享元工厂
- 状态变化可能影响共享逻辑
适用场景
- 大量相似对象
- 对象大部分状态可共享
- 内存受限场景
- 对象创建开销大
注意事项
内部状态必须不可变
外部状态由客户端管理
线程安全需考虑享元工厂
Java内置Integer、String常量池是享元应用
要点总结
- 享元模式共享内部状态,减少对象数量
- 内部状态共享存储,外部状态客户端保存
- 享元工厂管理享元对象池
- Java Integer缓存(-128~127)和String常量池是典型应用
- 适用于大量相似对象的内存优化场景
📝 发现内容有误?点击此处直接编辑