关闭

Python设计模式(十八)【享元模式】

标签: python设计模式class
1982人阅读 评论(0) 收藏 举报
分类:

即然选择了脚下这条路,就算是跪着都要把他走完。

# -*- coding: utf-8 -*-
"""
享元模式
"""
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

结果如图:

这里写图片描述

0
0
查看评论

python设计模式之享元模式

享元模式Flyweight模式,顾名思义,就是共享元数据,在python这个动态语言中可以提高程序性能和效率,比如从一个文件读取很多的字符串,而这些字符串必定重复,所以可以使用这个模式将其存在一个pool中python的例子(我将提出一系列的例子不同方式实现这个功能) 普通青年版,看了Gof,可能...
  • leongongye
  • leongongye
  • 2015-07-29 18:22
  • 638

享元模式(python)

享元模式:运用共享技术有效地支持大量细粒度的对象。 内部状态:享元对象中不会随环境改变而改变的共享部分。比如围棋棋子的颜色。 外部状态:随环境改变而改变、不可以共享的状态就是外部状态。比如围棋棋子的位置。 应用场景:程序中使用了大量的对象,如果删除对象的外部状态,可以用相对较少的共享对象取...
  • ponder008
  • ponder008
  • 2011-10-28 10:47
  • 1491

python设计模式(享元模式)

学习版本3.5.2 享元模式的概念:在一个系统中如果有多个相同的对象,那么只共享一份,不必每一个都去实例化一个对象。像python中的数字变量就是用的享元模式。 写一个例子,用享元对象去存字符串,在享元对象的工厂中包涵了享元对象池。 class Flyweight(object): d...
  • u013346751
  • u013346751
  • 2017-11-02 16:13
  • 23

享元模式

是对对象池的一种实现,共享对象,避免重复的创建,采用一个共享来避免大量拥有相同内容对象的开销。使用享元模式可有效支持大量的细粒度对象。如果很多很小的对象它们有很多相同的东西,并且在很多地方用到,那就可以把它们抽取成一个对象,把不同的东西变成外部的属性,作为方法的参数传入。
  • axi295309066
  • axi295309066
  • 2016-09-20 19:49
  • 823

设计模式(结构型)之享元模式(Flyweight Pattern)

当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。所以需要采用一个共享来避免大量拥有相同内容对象的开销。在Java中,String类型就是使用了享元模式。String对象是final类型,对象一旦创建就不可改变。在Java中字符串常量都是存在常量池中的,Java会...
  • yanbober
  • yanbober
  • 2015-05-04 14:15
  • 3153

设计模式读书笔记-----享元模式

面向对象可以非常方便的解决一些扩展性的问题,但是在这个过程中系统务必会产生一些类或者对象,如果系统中存在对象的个数过多时,将会导致系统的性能下降。对于这样的问题解决最简单直接的办法就是减少系统中对象的个数。        享元模式提供了一种解决方案,使用共享技...
  • chenssy
  • chenssy
  • 2013-09-20 16:49
  • 6792

23种设计模式之_享元模式

一什么是享元模式 二享元模式几个角色抽象享元类Flyweight 具体享元类FlyWeightAImlFlyWeightBIml 享元工厂类FlyweightFactoiy 客户类Client 三享元模式使用场景 四代码分析设计模式的熟练掌握,能够更容易理解系统的底层架构实现。一、什么是享元模式  ...
  • o279642707
  • o279642707
  • 2017-02-07 16:01
  • 506

Java设计模式——享元模式

在有大量对象时,有可能会造成内存溢出,我们把其中共同的部分抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建。
  • u013761665
  • u013761665
  • 2016-04-25 13:35
  • 11048

浅谈JAVA设计模式之——享元模式(Flyweight)

一、概述 运用共享技术有效地支持大量细粒度的对象。 二、适用性 当都具备下列情况时,使用Flyweight模式:        1.一个应用程序使用了大量的对象。       ...
  • l1028386804
  • l1028386804
  • 2015-05-07 23:46
  • 1657

设计模式---享元模式(C++实现)

享元模式(Flyweight Pattern)主要用于减少创建对象的数量,减少内存占用和提高性能。这种设计模式属于结构型模式,它提供了减少对象数量从而改善应用所需的对象结构的方式。 享元模式尝试重用现有的类对象,如果未找到匹配的对象则创建新的对象。 意图 运用共享技术有效的支持大量细粒...
  • My_heart_
  • My_heart_
  • 2017-03-16 14:48
  • 600
    个人资料
    • 访问:1294662次
    • 积分:18586
    • 等级:
    • 排名:第594名
    • 原创:312篇
    • 转载:932篇
    • 译文:123篇
    • 评论:297条
    博客专栏
    文章分类
    打赏
    如果你觉得我的文章对您有用,请随意打赏。 微信 支付宝