结构型设计模式,通过共享技术实现大量细粒度对象的复用,有效减少内存占用并提高性能。核心思想:分离内部状态(可共享)与外部状态(不可共享)
✅ 系统中存在大量相似对象
✅ 对象的大部分状态可以外部化
✅ 需要缓存池或对象池的应用
✅ 需要减少内存占用和提高性能的场景
角色 | 说明 |
---|---|
Flyweight | 抽象享元接口,定义操作接口 |
ConcreteFlyweight | 具体享元类,包含内部状态(可共享) |
UnsharedConcreteFlyweight | 非共享具体享元类(可选) |
FlyweightFactory | 享元工厂类,管理享元对象池 |
Client | 客户端,维护外部状态并调用享元对象 |
状态类型 | 说明 |
---|---|
内部状态 | 存储在享元对象内部,可以被多个上下文共享的信息 |
外部状态 | 随上下文变化的信息,由客户端保存并在调用时传入 |
// 抽象享元
interface Character {
void display(int x, int y, String color);
}
// 具体享元
class ConcreteCharacter implements Character {
private char symbol; // 内部状态
public ConcreteCharacter(char symbol) {
this.symbol = symbol;
}
@Override
public void display(int x, int y, String color) { // 外部状态
System.out.printf("显示字符 %c 在(%d,%d),颜色:%s%n", symbol, x, y, color);
}
}
// 享元工厂
class CharacterFactory {
private Map<Character, Character> pool = new HashMap<>();
public Character getCharacter(char key) {
if (!pool.containsKey(key)) {
pool.put(key, new ConcreteCharacter(key));
}
return pool.get(key);
}
}
// 客户端
public class Client {
public static void main(String[] args) {
CharacterFactory factory = new CharacterFactory();
List<Character> document = new ArrayList<>();
document.add(factory.getCharacter('H'));
document.add(factory.getCharacter('e'));
document.add(factory.getCharacter('l'));
document.add(factory.getCharacter('l'));
document.add(factory.getCharacter('o'));
int x = 0;
for (Character c : document) {
c.display(x++, 0, "black"); // 传递外部状态
}
}
}
✔️ 优点:
❌ 缺点:
模式 | 目的 | 关键区别 |
---|---|---|
单例模式 | 控制实例数量 | 享元可能有多个不同实例 |
原型模式 | 对象克隆 | 享元强调共享已有对象 |
对象池模式 | 重用对象 | 对象池管理临时对象,享元管理永久对象 |
记忆技巧:把享元模式想象成"共享单车"系统,单车(内部状态)是共享的,用户(外部状态)各自的使用位置不同。