享元模式(Flyweight Pattern)
为了解决什么问题?
享元模式主要解决的是在有大量相似对象时内存消耗过大的问题。通过共享相似的对象,减少系统中对象的数量,从而降低内存消耗,提高性能。
怎么用代码实现?
下面是Java代码示例,先定义享元接口和具体享元类:
/**
* 享元接口
*/
interface Flyweight {
void operation(String extrinsicState);
}
/**
* 具体享元类
*/
class ConcreteFlyweight implements Flyweight {
private String intrinsicState; // 内部状态
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void operation(String extrinsicState) {
System.out.println("Intrinsic State = " + intrinsicState + ", Extrinsic State = " + extrinsicState);
}
}
接着,定义享元工厂,用于生成或复用享元对象:
/**
* 享元工厂
*/
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String key) {
if (!flyweights.containsKey(key)) {
flyweights.put(key, new ConcreteFlyweight(key));
}
return flyweights.get(key);
}
}
最后,应用时在客户端调用享元工厂的方法获取享元对象来调用:
/**
* 客户端代码
*/
public class Client {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
Flyweight fw1 = factory.getFlyweight("a");
Flyweight fw2 = factory.getFlyweight("b");
Flyweight fw3 = factory.getFlyweight("a"); // 复用对象
fw1.operation("Operation 1");
fw2.operation("Operation 2");
fw3.operation("Operation 3"); // 注意,fw1 和 fw3 内部状态相同
}
}
为什么可以解决这个问题?
享元模式通过将对象的状态分为内部状态和外部状态,只有内部状态(共享状态)保存在享元对象内部。外部状态(非共享状态)可以在使用时动态地传入。这样设计使得同一个享元对象可以在不同的上下文中重用,从而减少对象的创建,降低了内存的使用,提高了程序的执行效率。
享元模式适用于哪些场景?
系统中存在大量相似对象:这些对象的大部分状态都可以是外部状态,而内部状态是相对稳定且可以共享的。
需要缓冲池的场景:如字符串常量池、数据库连接池等。
控制对象创建的系统:减少应用程序的内存使用,提高性能。
享元模式在开源代码的实际应用案例有:
Java字符串常量池:String类的intern()方法可以确保字符串常量池中只有一个String对象的实例。
GUI应用中的字符存储:在需要显示大量相同字符的GUI应用中,可以使用享元模式来减少字符对象的数量,每个字符对象只存储一次,而不是每次绘制时都创建。
通过有效地共享细粒度对象,享元模式可以在大量对象存在时显著地减少内存的使用,同时也可以提高应用程序的性能。
然而,使用享元模式需要维护一个存储享元对象的共享池,这可能会增加系统的复杂性。因此,在决定采用享元模式时,应当考虑其对性能的提升是否足以抵消增加的复杂性。
———————————这是分割线———————————
欢迎添加博主vx深入交流: