享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern)
享元模式是一种结构型设计模式,它通过共享多个对象之间的相同状态来减少内存使用。享元模式的核心思想是将对象的内部状态(不变的部分)和外部状态(变化的部分)分离,从而在有限的内存中存储更多的对象。
模式结构
- 享元接口(Flyweight)
定义享元对象的公共接口,声明操作外部状态的方法。 - 具体享元类(Concrete Flyweight)
实现享元接口,存储内部状态,并提供操作外部状态的方法。 - 享元工厂(Flyweight Factory)
负责创建和管理享元对象,确保合理地共享享元对象。 - 客户端(Client)
负责计算或存储享元的外部状态,并通过享元工厂获取享元对象。
代码示例
1. 享元接口(Flyweight)
// 享元接口:定义享元对象的公共接口
interface Flyweight {
void operation(int extrinsicState);
}
2. 具体享元类(Concrete Flyweight)
// 具体享元类:存储内部状态,并提供操作外部状态的方法
class ConcreteFlyweight implements Flyweight {
private final String intrinsicState; // 内部状态
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(int extrinsicState) {
System.out.println("Object address : " + System.identityHashCode(this));
System.out.println("IntrinsicState : " + intrinsicState);
System.out.println("ExtrinsicState : " + extrinsicState);
}
}
3. 享元工厂(Flyweight Factory)
// 享元工厂:负责创建和管理享元对象
class FlyweightFactory {
private final Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
ConcreteFlyweight flyweight = new ConcreteFlyweight(key);
flyweights.put(key, flyweight);
}
return flyweights.get(key);
}
}
4.调用示例
public class FlyweightPattern {
public static void main(String[] args) {
int extrinsicState = 22;
FlyweightFactory factory = new FlyweightFactory();
// 获取享元对象并操作
Flyweight flyweight1 = factory.getFlyweight("X");
flyweight1.operation(--extrinsicState);
Flyweight flyweight2 = factory.getFlyweight("X");
flyweight2.operation(--extrinsicState);
Flyweight flyweight3 = factory.getFlyweight("Z");
flyweight3.operation(--extrinsicState);
}
}
输出结果
Object address : 1023892928
IntrinsicState : X
ExtrinsicState : 21
Object address : 1023892928
IntrinsicState : X
ExtrinsicState : 20
Object address : 558638686
IntrinsicState : Z
ExtrinsicState : 19
应用场景
- 大量相似对象
当应用程序需要创建大量相似对象时,可以使用享元模式来减少内存开销。 - 内存限制
当内存有限时,享元模式可以通过共享对象的内部状态来节省内存。 - 对象状态分离
当对象的状态可以分为内部状态和外部状态时,可以使用享元模式来共享内部状态。
在Java中的应用
java.lang.Integer.valueOf(int)
Java中的包装类(如Integer
、Boolean
等)使用了享元模式来缓存常用的值,从而减少内存开销。- 字符串池
Java中的字符串常量池也是享元模式的一个应用,相同的字符串字面量会被共享。
优缺点
优点
- 减少内存使用
享元模式通过共享对象的内部状态,减少了内存中对象的数量。 - 提高性能
享元模式可以减少对象的创建和销毁,从而提高性能。
缺点
- 复杂性增加
享元模式需要将对象的状态分为内部状态和外部状态,增加了代码的复杂性。 - 牺牲执行速度
享元模式可能会牺牲执行速度来换取内存,因为每次调用时都需要重新计算外部状态。
总结
享元模式通过共享对象的内部状态来减少内存使用,适用于需要创建大量相似对象的场景。尽管它可能会增加代码的复杂性,但其优点在于提高了内存利用率和性能。在Java中,享元模式广泛应用于包装类和字符串常量池等场景。