美文网首页
【设计模式】【结构型模式】享元模式

【设计模式】【结构型模式】享元模式

作者: flowerAO | 来源:发表于2018-05-28 22:01 被阅读0次

    由于对象创建的开销,面向对象的系统可能会面临性能问题。性能问题通常在资源受限的嵌入式系统中出现,比如智能手机和平板电脑。大量复杂系统中也可能会出现同样的问题,因为要在其中创建大量对象,这些对象需要同时并存。
    这个问题之所以会发生,是因为当我们创建一个新对象时,需要分配额外的内存。虽然虚拟内存理论上为我们提供了无限制的内存空间,但现实并非如此。如果一个系统耗尽了所有的物理内存,就会开始将内存页替换到二级存储设备,通常是硬盘驱动器(Hard Disk Drive, HDD)。在多数情况下,由于内存和硬盘之间的性能差异,这是不能接受的。固态硬盘(Solid State Drive, SSD)的性能一般比硬盘要好,但并非人人都使用SSD,SSD并不会很快全面替代硬盘。
    除内存使用之外,计算性能也是一个考虑点。图形软件,包括计算机游戏,应该能够极快地渲染3D信息(例如,有成千上万棵树或满是士兵的村庄)。如果一个3D地带的每个对象都是单独创建,未使用数据共享,那么性能将是无法接受的。
    作为软件工程师,我们应该编写更好的软件来解决软件问题,而不是要求客户购买更多更好的硬件。享元设计模式通过为相似对象引入数据共享来最小化内存使用,提升性能。一个享元(Flyweight)就是一个包含状态独立的不可变数据的共存对象。依赖状态的可变数据不应该是享元的一部分,因为每个对象的这种信息都不同,无法共享。如果享元需要非固有数据,应该由客户端代码显示提供。
    若想要享元模式有效,需要满足以下几个条件

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

    实现

    # /usr/bin/python
    # coding:utf-8
    
    from enum import Enum
    import random
    import time
    
    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)
                obj.tree_type = tree_type
                cls.pool[tree_type] = obj
            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()
    
    
    

    输出

    render a tree of type TreeType.apple_tree and age 24 at (76, 36)
    render a tree of type TreeType.apple_tree and age 25 at (40, 53)
    render a tree of type TreeType.apple_tree and age 2 at (97, 74)
    render a tree of type TreeType.apple_tree and age 13 at (52, 51)
    render a tree of type TreeType.apple_tree and age 19 at (47, 26)
    render a tree of type TreeType.apple_tree and age 24 at (89, 38)
    render a tree of type TreeType.apple_tree and age 8 at (8, 91)
    render a tree of type TreeType.apple_tree and age 22 at (71, 70)
    render a tree of type TreeType.apple_tree and age 20 at (85, 29)
    render a tree of type TreeType.apple_tree and age 22 at (93, 10)
    render a tree of type TreeType.cherry_tree and age 27 at (45, 59)
    render a tree of type TreeType.cherry_tree and age 1 at (88, 76)
    render a tree of type TreeType.cherry_tree and age 22 at (51, 4)
    render a tree of type TreeType.peach_tree and age 30 at (44, 52)
    render a tree of type TreeType.peach_tree and age 3 at (66, 65)
    render a tree of type TreeType.peach_tree and age 28 at (56, 79)
    render a tree of type TreeType.peach_tree and age 2 at (10, 8)
    render a tree of type TreeType.peach_tree and age 7 at (32, 53)
    trees rendered: 18
    trees actually created: 3
    4378287632 == 4378287632? True
    4378287632 == 4378287576? False
    
    Process finished with exit code 0
    
    

    遗留问题

    • 监测程序执行时间和占用的内存

    • 元类的解释

    http://blog.jobbole.com/21351/
    https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python

    • function与method的区别
    >>> FooChild.echo_bar.__class__
    <class 'function'>
    >>> FooChild().echo_bar.__class__
    <class 'method'>
    

    https://teamtreehouse.com/community/difference-between-functions-and-methods-in-python

    • super的使用

    http://funhacks.net/explore-python/Class/super.html

    相关文章

      网友评论

          本文标题:【设计模式】【结构型模式】享元模式

          本文链接:https://www.haomeiwen.com/subject/kzebjftx.html