Python设计模式——享元模式(Flyweight)

享元模式(Flyweight)

享元模式是一个考虑系统性能的设计模式,通过使用享元模式可以节约内存空间,提高系统的性能。

享元模式以共享的方式高效地支持大量的细粒度对象,享元对象能做到共享的关键是区分内部状态(Internal State)和外部状态(External State)。

内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,因此内部状态可以共享。

外部状态是随环境改变而改变的、不可以共享的状态。享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。一个外部状态与另一个外部状态之间是相互独立的。

返回 Python设计模式-outline

示例


class Card:
    """The Flyweight"""

    # Could be a simple dict.
    # With WeakValueDictionary garbage collection can reclaim the object
    # when there are no other references to it.
    _pool: weakref.WeakValueDictionary = weakref.WeakValueDictionary()

    def __new__(cls, value, suit):
        # If the object exists in the pool - just return it
        obj = cls._pool.get(value + suit)
        # otherwise - create new one (and add it to the pool)
        if obj is None:
            obj = object.__new__(Card)
            cls._pool[value + suit] = obj
            # This row does the part we usually see in `__init__`
            obj.value, obj.suit = value, suit
        return obj

    # If you uncomment `__init__` and comment-out `__new__` -
    #   Card becomes normal (non-flyweight).
    # def __init__(self, value, suit):
    #     self.value, self.suit = value, suit

    def __repr__(self):
        return f"<Card: {self.value}{self.suit}>"

if __name__ == '__main__':
    c1 = Card('9', 'h')
    c2 = Card('9', 'h')
    c1, c2
    # 预期对象是相同的
    # (<Card: 9h>, <Card: 9h>)
    c1 == c2
    # True
    c1 is c2
    # True

    c1.new_attr = 'temp'
    c3 = Card('9', 'h')
    hasattr(c3, 'new_attr')
    # True

    Card._pool.clear()
    c4 = Card('9', 'h')
    hasattr(c4, 'new_attr')
    # False

示例2

也可以不用weakref,并且把判断实例是否存在的过程放在外部做。

class FlyWeight:
    def __init__(self, s):
        self.s = s

    def say(self):
        print(f"{self.s}:我是池子的一员")


class FlyWeightFactory:
    def __init__(self):
        self.d = {}

    def getFlyWeight(self, s):
        if s in self.d:
            return self.d[s]
        else:
            r = FlyWeight(s)
            self.d[s] = r
            return r


if __name__ == '__main__':
    f = FlyWeightFactory()
    d1 = f.getFlyWeight('one')
    d1.say()
    d2 = f.getFlyWeight('two')
    d2.say()
    d3 = f.getFlyWeight('one')
    d3.say()

ref

关于弱引用weakref: https://blog.csdn.net/Spade_/article/details/108114785

https://blog.csdn.net/qq_33511971/article/details/111185061

posted @   坦先生的AI资料室  阅读(150)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示