设计模式:享元模式(经典)

# 享元模式:享元模式是一种用于解决资源和性能压力时会使用到的设计模式,它的核心思想是通过引入数据共享(类__new__)来提升性能。

# 其实享元模式的实现与单例模式的实现方式十分相似,比如:
# 单例模式实现的是一个类对象只允许有一个实例对象,而享元模式则是一个类对象只允许创建不同类型的对象,这样保证同一类型的对象共享不可变数据。

# 场景: 在开发3D游戏时,例如有成千上万的士兵或者有成千上万棵树,如果一个3D地带的每个对象都单独创建,不使用数据共享,那么性能是无法接受的。
# 故享元设计模式就是通过为相似对象映入数据共享来最小化内存的使用,提升性能。
# 既然要创建成千上万个士兵,那么若他们的数据属性行为都是一样的,那岂不是黏一块去了。这时候就会有:可变数据和不可变数据的概念。
# 即 -- 重点在于将不可变(可共享)的属性与可变的属性区分开。
# 相同类型的对象共享不可变(可共享)的数据,而每个对象又有其独立的数据,这部分数据即为:可变的属性(不可共享数据)。

import random
from enum import Enum
TreeType = Enum('TreeType', 'apple_tree cherry_tree peach_tree')


class Tree:
    """
    该示例中,在__new__方法中实现类不可变数据的共享。
   在__init__方法中实现了可变数据的独立,即不共享。
    """
    pool = dict()

    def __new__(cls, tree_type, *args, **kwargs):
        obj = cls.pool.get(tree_type, None)
        if not obj:
            obj = super().__new__(cls, *args, **kwargs)
            cls.pool[tree_type] = obj
            obj.tree_type = tree_type
        return obj

    def __init(self, size):
        self.size = size

    def render(self, age, x, y):
        print('render a tree of type {} and age {} at ({},{})'.format(self.tree_type, age, x, y))


def main():
    rnd = random.Random()
    age_min, age_max = 1, 30
    min_piont, max_point = 0, 100
    tree_counter = 0

    for _ in range(10):
        t1 = Tree(TreeType.apple_tree)
        t1.render(rnd.randint(age_min, age_max),
                  rnd.randint(min_piont, max_point),
                  rnd.randint(min_piont, max_point)
                  )
        tree_counter += 1

    for _ in range(3):
        t1 = Tree(TreeType.cherry_tree)
        t1.render(rnd.randint(age_min, age_max),
                  rnd.randint(min_piont, max_point),
                  rnd.randint(min_piont, max_point)
                  )
        tree_counter += 1

    for _ in range(5):
        t1 = Tree(TreeType.peach_tree)
        t1.render(rnd.randint(age_min, age_max),
                  rnd.randint(min_piont, max_point),
                  rnd.randint(min_piont, max_point)
                  )
        tree_counter += 1

    print(Tree.pool)


if __name__ == '__main__':
    main()

  

 

posted @ 2020-08-20 18:30  Adamanter  阅读(156)  评论(0)    收藏  举报