享元模式

由于对象创建的开销,面向对象的系统可能还面临性能问题,性能问题通常在资源受限的嵌入式系统中出现,比如智能手机和平板电脑。大型复杂系统中也可能会出现同样问题,因为要在其中创建大量对象,这些对象需要同时并存。

 

eg:如果一个3D地带的每个对象都是单独创建,未使用数据共享,那么性能将是无法接受的。

享元模式通过为相似对象引入数据共享来最小化内存使用,提升性能
一个享元就是一个包含状态独立的不可变数据的共享对象;
依赖状态改的可变数据不应该是享元的一部分,因为每个对象的这种信息不同,无法共享;如果享元需要非固有的数据,应该有客户端代码显式的提供
例子:
  FPS游戏:士兵->拥有相同的状态(看起来一样,跑,跳)
  不同的状态(枪支,健康状况,地理位置)

 

若想要享元模式有效,需满足的条件

  1. 应用需要大量的对象
  2. 对象太多,存储/渲染他们的代价带大。一旦移除对象中的可变状态(因为在需要之时,应该有客户端代码显式地传递给享元),多组不同的对象可被更少的共享对象替代。
  3. 对象ID对应用不重要。对象共享会造成ID比较失败,所以不能依赖对象ID(那些在客户端代码看来不同的对象,最终具有相同的ID)

 

 以下是在一个场景展示18棵树,但是实际上我们只创建了3棵树而已

# coding: utf-8

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)
        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))


def main():
    rnd = random.Random()
    age_min, age_max = 1, 30  # 单位为年
    min_point, 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_point, max_point),
                  rnd.randint(min_point, max_point))
        tree_counter += 1

    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

    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('trees 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)))


if __name__ == '__main__':
    main()

 

posted @ 2018-12-17 14:49  慕沁  阅读(109)  评论(0)    收藏  举报