Python设计模式详解之11 —— 享元模式

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  |
                                                           +--------------------+
  1. Flyweight(享元接口)
    定义一个方法,用于接收外部状态。

  2. ConcreteFlyweight(具体享元类)
    实现享元接口,存储内部状态。

  3. FlyweightFactory(享元工厂类)
    管理享元对象的创建和共享,确保相同的享元对象被重复使用。

  4. 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

模式分析

优点
  1. 内存优化:通过共享对象,减少重复对象的创建。
  2. 性能提升:减少内存占用和GC的压力。
缺点
  1. 复杂性增加:需要维护内部和外部状态的分离。
  2. 线程安全问题:共享对象需要考虑多线程环境下的一致性。
使用场景
  1. 文字处理:文本编辑器中共享字符对象。
  2. 游戏开发:场景中重复的树木、建筑等。
  3. 图形应用:共享的图形或样式。

通过合理设计内部和外部状态,并结合工厂模式管理对象,Flyweight模式可以显著提高系统资源的利用效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾工

雁过留声

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值