享元模式:内存优化的终极武器🎯,共享对象的极致艺术!
文章目录
前言:为什么需要享元模式?🤔
各位宝子们,今天我们来聊一个设计模式界的"节约达人"——享元模式!😎 还在为创建大量相似对象导致内存爆炸而头疼吗?还在为系统性能下降而烦恼吗?享元模式来拯救你啦!
享元模式是设计模式家族中的"内存管家",它能帮我们优雅地共享对象,大幅减少内存占用,提升系统性能。今天就带大家彻底搞懂这个"看似简单,实则精妙"的设计模式!💯
一、享元模式:对象共享的艺术 🎨
1.1 什么是享元模式?
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享技术有效地支持大量细粒度对象的复用。当系统中存在大量相似对象时,享元模式可以极大地减少内存占用,提高系统性能。就像一个图书馆,不需要为每个读者都购买一本相同的书,而是让多个读者共享同一本书!📚
1.2 为什么需要享元模式?
想象一下这些场景:
- 系统需要创建大量相似的对象
- 这些对象消耗大量内存
- 对象的大部分状态都可以变为外部状态
- 剥离外部状态后,可以用相对较少的共享对象取代大量对象
- 应用程序不依赖于对象标识(即对象的身份不重要)
这些场景有什么共同点?它们都涉及到大量相似对象导致的内存压力问题。享元模式就是为这些场景量身定制的!🚀
二、享元模式的核心概念:内部状态与外部状态 🧩
享元模式的核心在于区分对象的两种状态:
- 内部状态(Intrinsic State):存储在享元对象内部,不会随环境改变而改变的状态,可以共享。
- 外部状态(Extrinsic State):随环境改变而改变的状态,不可以共享,需要由客户端保存。
举个例子:一个文字编辑器中的字符对象。字符的字体、大小、样式等是内部状态(可以共享),而字符的位置、颜色等是外部状态(不可共享)。
// 享元接口
public interface Character {
void display(int x, int y, String color); // x, y, color是外部状态
}
// 具体享元类
public class ConcreteCharacter implements Character {
private char symbol; // 内部状态 - 字符符号
private String font; // 内部状态 - 字体
private int size; // 内部状态 - 大小
public ConcreteCharacter(char symbol, String font, int size) {
this.symbol = symbol;
this.font = font;
this.size = size;
}
@Override
public void display(int x, int y, String color) {
// 外部状态作为参数传入
System.out.println("显示字符: " + symbol + ", 字体: " + font + ", 大小: " + size +
", 位置: (" + x + "," + y + "), 颜色: " + color);
}
}
三、享元模式的结构与实现 🏗️
3.1 享元模式的核心结构
享元模式包含以下几个角色:
- 享元接口(Flyweight):定义享元对象的接口,通过这个接口享元可以接受并作用于外部状态
- 具体享元(Concrete Flyweight):实现享元接口,存储内部状态
- 享元工厂(Flyweight Factory):创建并管理享元对象,确保享元对象被合理地共享
- 客户端(Client):维护对享元的引用,计算或存储享元的外部状态
3.2 享元模式的完整实现
让我们实现一个完整的文字编辑器的例子:
// 享元接口
public interface Character {
void display(int x, int y, String color); // 外部状态作为参数传入
}
// 具体享元类
public class ConcreteCharacter implements Character {
private char symbol; // 内部状态
private String font;
private int size;
public ConcreteCharacter(char symbol, String font, int size) {
this.symbol = symbol;
this.font = font;
this.size = size;
System.out.println("创建字符对象: " + symbol + ", 字体: " + font + ", 大小: " + size);
}
@Override
public void display(int x, int y, String color) {
System.out.println("显示字符: " + symbol + ", 字体: " + font + ", 大小: " + size +
", 位置: (" + x + "," + y + "), 颜色: " + color);
}
}
// 享元工厂
public class CharacterFactory {
private Map<Character, Character> characters = new HashMap<>();
public Character getCharacter(char symbol, String font, int size) {
// 创建key
Character key = symbol;
// 检查是否已经存在该字符的享元对象
if (!characters.containsKey(key)) {
// 不存在则创建新的享元对象
characters.put(key, new ConcreteCharacter(symbol, font, size));
}
return characters.get(key);
}
public int getCharacterCount() {
return characters.size();
}
}
// 客户端代码
public class TextEditor {
public static void main(String[] args) {
CharacterFactory factory = new CharacterFactory();
// 使用享元对象
String text = "Hello, World!"<