美文网首页Python设计模式
Python设计模式 - 享元模式

Python设计模式 - 享元模式

作者: jumo | 来源:发表于2020-02-21 10:53 被阅读0次

"""

享元模式:运用共享技术有效地支持大量细粒度的对象。

内部状态:享元对象中不会随环境改变而改变的共享部分。比如围棋棋子的颜色。

外部状态:随环境改变而改变、不可以共享的状态就是外部状态。比如围棋棋子的位置。

应用场景:程序中使用了大量的对象,如果删除对象的外部状态,可以用相对较少的共享对象取代很多组对象,就可以考虑使用享元模式。

"""

import weakref

class FlyweightMeta(type):

    def __new__(mcs, name, parents, dct):

        """

        name: 类名

        parents: 父类

        dct: 包括类属性,类方法,静态方法等的字典

        :return:新类

        """

        # 设置实例池

        #创建value为弱引用对象的字典

        dct['pool'] = weakref.WeakValueDictionary()

        return super(FlyweightMeta, mcs).__new__(mcs, name, parents, dct)

    @staticmethod

    def _serialize_params(cls, *args, **kwargs):

        """

        序列化输入参数到key。

        简单的实现仅仅是序列化作为一个字符串

        """

        args_list = map(str, args)

        args_list.extend([str(kwargs), cls.__name__])

        key = ''.join(args_list)

        return key

    """ Python中有一个有趣的语法,只要定义类型的时候,实现__call__函数,这个类型就成为可调用的。

   换句话说,我们可以把这个类的对象当作函数来使用,相当于重载了括号运算符。"""

    def __call__(cls, *args, **kwargs):

        key = FlyweightMeta._serialize_params(cls, *args, **kwargs)

        """如果cls对象中有属性pool则获取对象,否则设置空字典"""

        pool = getattr(cls, 'pool', {})

        instance = pool.get(key)

        if not instance:

            instance = super(FlyweightMeta, cls).__call__(*args, **kwargs)

            pool[key] = instance

        return instance

class Card(object):

    """

       对象池。内置引用计数

    """

    _CardPool = weakref.WeakValueDictionary()

    """享元模式 实现. 如果池中存在对象就返回它(而不是创建一个新的)"""

    def __new__(cls, value, suit):

        obj = Card._CardPool.get(value + suit)

        if not obj:

            obj = object.__new__(cls)

            Card._CardPool[value + suit] = obj

            obj.value, obj.suit = value, suit

        return obj

    # def __init__(self, value, suit):

    #     self.value, self.suit = value, suit

    def __repr__(self):

        return "<Card: %s%s>" % (self.value, self.suit)

class Card2(object):

    __metaclass__ = FlyweightMeta

    def __init__(self, *args, **kwargs):

        # print('Init {}: {}'.format(self.__class__, (args, kwargs)))

        pass

if __name__ == '__main__':

    import sys

    if sys.version_info[0] > 2:

        sys.stderr.write("!!! This example is compatible only with Python 2 ATM !!!\n")

        raise SystemExit(0)

    #注释__new__ 并取消注释 __init__看出区别

    c1 = Card('9', 'h')

    c2 = Card('9', 'h')

    print(c1, c2)

    print(c1 == c2, c1 is c2)

    print(id(c1), id(c2))

    c1.temp = None

    c3 = Card('9', 'h')

    print(hasattr(c3, 'temp'))

    c1 = c2 = c3 = None

    c3 = Card('9', 'h')

    print(hasattr(c3, 'temp'))

    # 元类 测试

    instances_pool = getattr(Card2, 'pool')

    cm1 = Card2('10', 'h', a=1)

    cm2 = Card2('10', 'h', a=1)

    cm3 = Card2('10', 'h', a=2)

    assert (cm1 == cm2) != cm3

    assert (cm1 is cm2) is not cm3

    assert len(instances_pool) == 2

    del cm1

    assert len(instances_pool) == 2

    del cm2

    assert len(instances_pool) == 1

    del cm3

    assert len(instances_pool) == 0

相关文章

  • 好程序员Java培训​分享java设计模式之享元模式

    好程序员Java培训​分享java设计模式之享元模式,Java设计模式中的享元模式。享元模式有点类似于单例...

  • Java设计模式——享元模式

    Java设计模式之享元模式 这期跟大家聊的的设计模式是享元模式,该模式也是结构模式。 简介 利用共享的方式解决大量...

  • Java设计模式_享元模式

    点击链接跳转:设计模式——享元模式

  • Python设计模式 - 享元模式

    """ 享元模式:运用共享技术有效地支持大量细粒度的对象。 内部状态:享元对象中不会随环境改变而改变的共享部分。比...

  • 二十一、享元模式

    1. 何为享元模式 定义:通过共享已存在的对象,减少创建对象内存开销的设计模式被称为享元模式。 享元模式和单例模式...

  • 享元模式

    swift实战-享元模式 概论:通过共享已存在的对象,减少创建对象内存开销的设计模式被称作享元模式 享元模式Fly...

  • 好程序员Java培训精讲  java设计模式—享元模式

    好程序员Java培训精讲 java设计模式—享元模式 一、关于享元模式 享元模式有点类似于单例模式,都是只生成一个...

  • Java设计模式系列-享元模式

    原创文章,转载请标注出处:《Java设计模式系列-享元模式》 一、概述 享元模式:“享”就是分享之意,指一物被众人...

  • Android 享元模式

    Android 设计模式系列文章 Android 23种设计模式 一、前言 享元模式即:Flyweight,它是对...

  • Python设计模式之享元模式

    享元模式 由于对象创建的开销,面向对象的系统可能会面临性能问题。性能问题通常在资源受限的嵌入式系统中出现,比如智能...

网友评论

    本文标题:Python设计模式 - 享元模式

    本文链接:https://www.haomeiwen.com/subject/knaqqhtx.html