享元模式概念:

        运用共享技术有效的支持大量细粒度的对象。。简单来说,在我们玩游戏的时候,场景中有一万棵密密麻麻的树,难道我们要把树实例化一万次吗?  你要知道,实例化一万次,内存是要爆炸的,这里我们就可以用享元模式。 实例化一次树,描绘千万棵树的时候只是将坐标改一下。

满足一下条件可以用享元模式:

  •   ①:应用需要使用大量的对象
  •   ②:对象太多,存储/渲染它们的代价太大。 存在多组不同的对象可被相对更少的共享数据所替代。
  •   ③:对象ID对于应用不重要,对象共享会造成ID的破坏。

案例一:

       我们这里就实现概念中我刚才举的那个例子。  这里有三种树: apple_tree,cherry_tree,peach_tree。同一种类型,我们这里只能实例化一次。在Tree中的__new__()方法中进行控制,跟单例模式有点像哦。对象创建好,我们把对象放在一个pool字典中,为了在后面验证我们对每棵树真的只实例化了一次。在Tree类中,我们还定义了一个render()方法,可以理解为描绘树的一个函数。  

      接下来看main方法中,  树的年龄让随机产生,树的坐标也让随机产生。。开始生产树了。首先对apple_tree创了10棵,其实每次实例化的时候都是那个对象,只不过改了坐标和树的年龄,同理创建了cherry_tree树3棵,peach_tree树5棵。  最后我们验证了: 传入不同的树,创建不同的对象,传入相同的树,创建的对象是相同的(同一个)。

import random
from enum import Enum

TreeType = Enum('TreeType', 'apple_tree cherry_tree peach_tree')

class Tree:
    pool = dict()

    def __new__(cls, tree_type):
        obj = cls.pool.get(tree_type, None)    # 获取字典中tree_type数据,若没有则返回的是None
        if not obj:
            obj = object.__new__(cls)
            cls.pool[tree_type] = obj
            obj.tree_type = tree_type
        return obj

    def render(self, age, x, y):
        print('render a tree of type {} and age {} at {},{}'.format(self.tree_type, age, x, y))
if __name__ == '__main__':
    rnd = random.Random()
    age_min, age_max = 1, 30
    min_point, max_point = 0, 100
    tree_counter = 0

    # 10棵苹果树
    for _ in range(10):
        t1 = Tree(TreeType.apple_tree)
        t1.render(rnd.randint(age_min, age_max),
                  rnd.randint(min_point, max_point),
                  rnd.randint(min_point, max_point))
        tree_counter += 1

    # 3棵樱桃树
    for _ in range(3):
        t2 = Tree(TreeType.cherry_tree)
        t2.render(rnd.randint(age_min, age_max),
                  rnd.randint(min_point, max_point),
                  rnd.randint(min_point, max_point))
        tree_counter += 1

    # 5棵树
    for _ in range(5):
        t3 = Tree(TreeType.peach_tree)
        t3.render(rnd.randint(age_min, age_max),
                  rnd.randint(min_point, max_point),
                  rnd.randint(min_point, max_point))
        tree_counter += 1

    print('trees rendered: {}'.format(tree_counter))
    print('tree actually created: {}'.format(len(Tree.pool)))

    t4 = Tree(TreeType.cherry_tree)
    t5 = Tree(TreeType.cherry_tree)
    t6 = Tree(TreeType.apple_tree)

    print('{} == {} ? {}'.format(id(t4), id(t5), id(t4) == id(t5)))
    print('{} == {} ? {}'.format(id(t5), id(t6), id(t5) == id(t6)))

  程序的输出结果: