概念
通过共享对象,减少系统中对象的数量,从而节省内存,提高性能
应用场景
当需要创建大量相似对象时,使用享元模式可以将对象中相同的部分提取出来作为共享对象,保留特殊的不可共享部分,减少了重复创建相同的部分。

基本结构

1)抽象享元(Flyweight):定义享元对象的接口,规定非重复部分传入的标准方法
2)具体享元(ConcreteFlyweight):实现抽象享元接口,内部保存可以共享的状态
3)享元工厂(FlyweightFactory):负责创建和管理享元对象,确保相同的享元对象只被创建一次,并进行共享
4)客户端(Client):通过享元工厂获取享元对象,同时传入外部状态进行使用
代码实现
以 “字符缓存系统” 为例
享元接口
规定非重复部分传入的标准方法,实现统一管理各种字符
public interface Glyph {
void render(int x, int y, String color);
}
具体享元
只保留不变的信息
public class CharacterGlyph implements Glyph {
private final char symbol; // 内部状态,不随使用变化
private final String font; // 内部状态:字体
public CharacterGlyph(char symbol, String font) {
this.symbol = symbol;
this.font = font;
}
@Override
public void render(int x, int y, String color) {
System.out.println("渲染字符 '" + symbol + "',字体:" + font + ",颜色:" + color + ",位置:(" + x + "," + y + ")");
}
}
享元工厂
提供了享元对象的集中管理,相同的对象最多只有一个实例
public class GlyphFactory {
private Map<String, Glyph> glyphPool = new HashMap<>();
public Glyph getGlyph(char symbol, String font) {
String key = symbol + ":" + font;
if (!glyphPool.containsKey(key)) {
glyphPool.put(key, new CharacterGlyph(symbol, font));
}
return glyphPool.get(key);
}
}
客户端调用
1)定义包含外部状态的类:
包含对共享对象的引用,注意共享对象一定为final类型
public class CharacterView {
private final Glyph glyph;
private final int x;
private final int y;
private final String color;
public CharacterView(Glyph glyph, int x, int y, String color) {
this.glyph = glyph;
this.x = x;
this.y = y;
this.color = color;
}
public void draw() {
glyph.render(x, y, color);
}
}
2)使用
通过享元工厂获取共享部分的对象。
public class Client {
public static void main(String[] args) {
GlyphFactory factory = new GlyphFactory();
CharacterView[] page = new CharacterView[] {
new CharacterView(factory.getGlyph('a', "Arial"), 10, 10, "black"),
new CharacterView(factory.getGlyph('b', "Arial"), 20, 10, "black"),
new CharacterView(factory.getGlyph('a', "Arial"), 30, 10, "red"),
new CharacterView(factory.getGlyph('a', "Arial"), 40, 10, "blue"),
new CharacterView(factory.getGlyph('b', "Arial"), 50, 10, "black"),
};
for (CharacterView cv : page) {
cv.draw();
}
}
}
优缺点
优点
1)节省内存:通过共享对象来减少内存的使用,尤其在需要大量相似对象时
2)提高性能:通过对象的共享,减少了对象的创建和销毁,尤其是在大量对象需要频繁创建的场景中
缺点
1)资源竞争:多个对象共享同一个实例时,如果共享的对象没有正确同步,可能会导致资源竞争或线程安全问题
