享元模式(Flyweight Pattern)
享元模式是一种结构型设计模式,通过共享技术来支持大量细粒度对象的复用。它的核心思想是:当系统中存在大量相同或相似的对象时,只创建一个共享实例,而不是为每个使用场景都创建新对象。
核心概念
-
- 内部状态(Intrinsic State)
- 可以共享的、不变的状态
- 存储在享元对象内部
- 不随环境改变
-
- 外部状态(Extrinsic State)
- 不能共享的、变化的状态
- 由客户端维护
- 在使用时传递给享元对象
实际应用示例: 文字处理器(字符共享)
python
class Character:
"""字符享元类"""
def __init__(self, char, font_family, font_size):
# 内部状态:字符本身和字体属性
self.char = char
self.font_family = font_family
self.font_size = font_size
def display(self, position_x, position_y):
"""
显示字符
外部状态:位置坐标
"""
print(f"字符 '{self.char}' [{self.font_family}, {self.font_size}pt] "
f"显示在位置({position_x}, {position_y})")
class CharacterFactory:
"""字符工厂 - 负责创建和管理享元对象"""
def __init__(self):
self._characters = {}
def get_character(self, char, font_family, font_size):
"""获取字符享元"""
key = (char, font_family, font_size)
if key not in self._characters:
print(f"创建新的字符对象: {char} ({font_family}, {font_size}pt)")
self._characters[key] = Character(char, font_family, font_size)
else:
print(f"复用已有字符对象: {char} ({font_family}, {font_size}pt)")
return self._characters[key]
def get_total_characters(self):
"""获取创建的字符总数"""
return len(self._characters)
class TextEditor:
"""文本编辑器 - 客户端"""
def __init__(self):
self.factory = CharacterFactory()
self.text = [] # 存储(字符享元, x, y)的列表
def insert_text(self, text, font_family, font_size, start_x, start_y):
"""插入文本"""
x, y = start_x, start_y
for char in text:
if char != ' ': # 空格也处理,但为了简洁,这里忽略
# 获取字符享元
char_flyweight = self.factory.get_character(char, font_family, font_size)
# 存储字符和位置
self.text.append((char_flyweight, x, y))
x += font_size # 简单的字符间距计算
else:
x += font_size // 2 # 空格间距
def display_all(self):
"""显示所有文本"""
print("\n=== 文本内容 ===")
for char_flyweight, x, y in self.text:
char_flyweight.display(x, y)
def text_editor_example():
print("=== 文字处理器示例 ===")
editor = TextEditor()
# 插入多行文本
editor.insert_text("Hello", "Arial", 12, 10, 10)
editor.insert_text("World", "Arial", 12, 10, 30)
editor.insert_text("Hello", "Times New Roman", 14, 10, 50)
editor.display_all()
print(f"\n总共创建的字符对象数: {editor.factory.get_total_characters()}")
print(f"显示的字符总数: {len(editor.text)}")
if __name__ == "__main__":
text_editor_example()