享元模式

意图
运用共享技术有效地支持大量细粒度的对象。
 
适用性:
一个应用程序使用了大量的对象。
完全由于使用大量的对象,造成很大的存储开销。
对象的大多数状态都可变为外部状态。
如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。 
应用程序不依赖于对象标识。由于Flyweight 对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。
 
代码示例:
#-*- coding:utf-8 -*-
'''
Flyweight
'''
class FlyweightBase(object):
    _instances = dict()  #皴法实例化的对象内存地址
    def __init__(self,*args,**kwargs):
        #继承的子类必须初始化
        raise NotImplementedError
 
    def __new__(cls, *args, **kwargs):
        print(cls._instances,type(cls))  #cls 就是你要实例化的子类如:obj = Spam(1,abc)
        return cls._instances.setdefault(
            (cls,args,tuple(kwargs.items())), #key   (实例和参数)obj = Spam(y,x)
            super(FlyweightBase,cls).__new__(cls)  # value  #实例化新的对象的内存地址
            # 调用自身的_instances字典,如果没有往父类找_instances字典
            # setdefault:判断_instances字典是否有该key:obj = Spam(y,x)实例 ,
            #               如果有,返回该key的value(上次实例化对象(内存地址))
            # setdefault: 如果找不到key:obj = Spam(y,x)实例 ,就在_instances字典就创建该key,value为新实例化对象(内存地址)
            #               返回该新创建key的value(该次实例化的对象(内存地址)
            # 这也就说明你实例化对象的时候,如果形参相同的话,不用实例化,直接返回已存在的实例的内存)
        )
class Spam(FlyweightBase):
    '''精子类'''
    def test_data(self):
        pass
    def __init__(self,a,b):
        self.a = a
        self.b = b
 
    def test_data(self):
        print("精子准备好了",self.a,self.b)
        
class Egg(FlyweightBase):
    '''卵类'''
    def __init__(self,x,y):
        self.x = x
        self.y = y
 
    def test_data(self):
        print("卵子准备好了",self.x,self.y)
 
spam1 = Spam(1,'abc')
spam2 = Spam(1,'abc')
spam3 = Spam(3,'DEF')
egg1 = Egg(1,'abc')
print(id(spam1),id(spam2),id(spam3))
 
#egg2 = Egg(4,'abc')
# assert spam1 is spam2
# assert egg1 is not spam1
# print(id(spam1),id(spam2))
# spam2.test_data()
# egg1.test_data()
# print(egg1._instances)
# print(egg1._instances.keys())
执行结果:
通过代码了解:在单例的基础上做了改动,也就是当你实例化一个对象,就判断你实例化的该对象(包含形参)是否存在父类的指定的字典,存在就把之前实例化对象返回给你(等于没创建新的示例,而是赋值多一个变量而已,指向同一个内存地址),如果不存在,就创建新的实例化对象返回,并且存放在指定字典
 

原文地址:https://www.cnblogs.com/absoluteli/p/14124053.html