Flyweight(享元)设计模式是一种结构型设计模式,旨在通过共享相同的对象以减少内存使用和对象创建的开销。它非常适合应用于需要创建大量细粒度对象的场景,例如图形编辑器中的形状、文字处理软件中的字符等。
模式意图
- 目的:通过共享尽可能多的对象来支持大量细粒度对象的高效使用。
- 核心思想:将对象的状态分为内部状态和外部状态。
- 内部状态:对象共享的状态,存储在享元对象内部,不随环境改变。
- 外部状态:对象特有的状态,存储在客户端,由客户端传递给享元对象。
组成部分
以下是享元模式的核心结构:
+--------------------+ +--------------------+ +--------------------+ +--------------------+
| Flyweight |<-------| ConcreteFlyweight |<-------| FlyweightFactory |<-------| Client |
+--------------------+ +--------------------+ +--------------------+ +--------------------+
| + operation(extr): | | - intr: Any | | - flyweights: dict | | - extr: Any |
| void | | + operation(extr): | | + get_flyweight( | | + use_flyweight(): |
| | | void | | key): Flyweight | | void |
+--------------------+ +--------------------+ | + create_flyweight(| +--------------------+
| key): Flyweight |
+--------------------+
-
Flyweight(享元接口)
定义一个方法,用于接收外部状态。 -
ConcreteFlyweight(具体享元类)
实现享元接口,存储内部状态。 -
FlyweightFactory(享元工厂类)
管理享元对象的创建和共享,确保相同的享元对象被重复使用。 -
Client(客户端)
负责维护外部状态,并调用享元对象的方法。
Python实现
以下示例展示了使用享元模式优化绘制树的操作:
class TreeType:
"""享元类,表示树的类型(内部状态)"""
def __init__(self, name, color, texture):
self.name = name
self.color = color
self.texture = texture
def draw(self, x, y):
"""绘制树时需要外部状态(位置)"""
print(f"Drawing {self.name} tree at ({x}, {y}) with color {self.color} and texture {self.texture}")
class TreeFactory:
"""享元工厂类,管理树类型的共享"""
_tree_types = {}
@classmethod
def get_tree_type(cls, name, color, texture):
key = (name, color, texture)
if key not in cls._tree_types:
cls._tree_types[key] = TreeType(name, color, texture)
print(f"Created new TreeType: {key}")
else:
print(f"Reusing existing TreeType: {key}")
return cls._tree_types[key]
class Tree:
"""具体的树类,包含位置(外部状态)和树类型(享元)"""
def __init__(self, x, y, tree_type):
self.x = x
self.y = y
self.tree_type = tree_type
def draw(self):
self.tree_type.draw(self.x, self.y)
class Forest:
"""客户端类,管理树的集合"""
def __init__(self):
self.trees = []
def plant_tree(self, x, y, name, color, texture):
tree_type = TreeFactory.get_tree_type(name, color, texture)
tree = Tree(x, y, tree_type)
self.trees.append(tree)
def draw(self):
for tree in self.trees:
tree.draw()
# 使用示例
forest = Forest()
forest.plant_tree(10, 20, "Oak", "Green", "Rough")
forest.plant_tree(15, 25, "Oak", "Green", "Rough")
forest.plant_tree(20, 30, "Pine", "Dark Green", "Smooth")
forest.draw()
输出示例
Created new TreeType: ('Oak', 'Green', 'Rough')
Reusing existing TreeType: ('Oak', 'Green', 'Rough')
Created new TreeType: ('Pine', 'Dark Green', 'Smooth')
Drawing Oak tree at (10, 20) with color Green and texture Rough
Drawing Oak tree at (15, 25) with color Green and texture Rough
Drawing Pine tree at (20, 30) with color Dark Green and texture Smooth
模式分析
优点
- 内存优化:通过共享对象,减少重复对象的创建。
- 性能提升:减少内存占用和GC的压力。
缺点
- 复杂性增加:需要维护内部和外部状态的分离。
- 线程安全问题:共享对象需要考虑多线程环境下的一致性。
使用场景
- 文字处理:文本编辑器中共享字符对象。
- 游戏开发:场景中重复的树木、建筑等。
- 图形应用:共享的图形或样式。
通过合理设计内部和外部状态,并结合工厂模式管理对象,Flyweight模式可以显著提高系统资源的利用效率。