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 @ 2022-07-26 17:45  坦先生的AI资料室  阅读(146)  评论(0编辑  收藏  举报