享元模式(Flyweight Pattern)概述
定义
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享相同的对象来减少内存的使用,特别适用于对象数量庞大且相似的场景。通过共享相同的对象来减少内存的使用,并确保在需要的时候能够快速地访问和使用对象。
享元模式的核心思想是:
- 对于相同内容的对象进行共享,避免每次都创建相同对象。
- 通过将共享的部分提取到外部的享元池中,节省内存开销。
- 享元模式的关键是将不可变部分(共享部分)提取到外部,避免重复存储。
享元模式的角色
- 享元(Flyweight):享元对象可以通过共享来降低内存的消耗。享元对象通常有两个部分:
- 内部状态(Intrinsic State):可以被多个对象共享的部分。
- 外部状态(Extrinsic State):对象的具体使用状态,每个对象可能不同。
- 具体享元(ConcreteFlyweight):实现享元接口,存储内部状态。
- 享元工厂(FlyweightFactory):负责管理享元对象的创建,确保共享对象的复用。
- 客户端(Client):使用享元对象,并维护外部状态。
示例:文字字符的共享
假设我们需要在文本编辑器中显示字符,我们不希望每个字符都创建一个独立的对象,而是共享相同字符的对象(如字母 "A" 和字母 "B")。
Java 实现代码
import java.util.HashMap;
import java.util.Map;
// 享元接口
interface Flyweight {
void display(String extrinsicState);
}
// 具体享元类
class ConcreteFlyweight implements Flyweight {
private String intrinsicState; // 内部状态
public ConcreteFlyweight(String intrinsicState) {
this.intrinsicState = intrinsicState;
}
@Override
public void display(String extrinsicState) {
System.out.println("字符: " + intrinsicState + ", 位置: " + extrinsicState);
}
}
// 享元工厂
class FlyweightFactory {
private Map<String, Flyweight> flyweights = new HashMap<>();
public Flyweight getFlyweight(String intrinsicState) {
if (!flyweights.containsKey(intrinsicState)) {
flyweights.put(intrinsicState, new ConcreteFlyweight(intrinsicState));
}
return flyweights.get(intrinsicState);
}
public int getFlyweightCount() {
return flyweights.size();
}
}
// 客户端
public class FlyweightPatternDemo {
public static void main(String[] args) {
FlyweightFactory factory = new FlyweightFactory();
// 获取共享对象
Flyweight flyweight1 = factory.getFlyweight("A");
Flyweight flyweight2 = factory.getFlyweight("B");
Flyweight flyweight3 = factory.getFlyweight("A");
// 显示对象,传入外部状态(如字符位置)
flyweight1.display("位置1");
flyweight2.display("位置2");
flyweight3.display("位置3");
System.out.println("享元对象的数量: " + factory.getFlyweightCount());
}
}
输出结果
字符: A, 位置: 位置1
字符: B, 位置: 位置2
字符: A, 位置: 位置3
享元对象的数量: 2
享元模式的优点
- 减少内存使用:通过共享相同的对象,节省了大量的内存空间。
- 提高性能:避免重复创建相同的对象,减少了对象的创建和销毁的时间开销。
- 提高系统可扩展性:可以轻松地添加新的享元对象,不需要改变现有的代码结构。
享元模式的缺点
- 增加复杂度:由于享元模式通过共享对象管理状态,可能会使系统设计变得复杂。
- 不适用所有场景:享元模式适用于状态可以共享的对象,但如果对象状态差异较大,享元模式就不太适用。
使用场景
- 字符串池:Java 中的字符串池就是利用享元模式来管理相同内容的字符串对象,避免重复创建相同的字符串。
- 大规模的图形绘制:比如在游戏中,不同的敌人可能有相同的外观(颜色、形状等),但它们的具体位置不同,可以通过享元模式来减少内存的消耗。
- 文本编辑器:每个字符的显示可以看作一个享元对象,其中字符本身是共享的,而字符的位置则是外部状态。
通过享元模式,系统能够显著减少对象的创建数量和内存使用,尤其是在处理大量相似对象时,享元模式非常有效。
标签:享元,对象,模式,Flyweight,共享,设计模式,intrinsicState From: https://www.cnblogs.com/pangchunlei/p/18674321