zoukankan      html  css  js  c++  java
  • Flyweight享元模式(结构型模式)

    1、面向对象的缺点 

    虽然OOP能很好的解决系统抽象的问题,并且在大多数的情况下,也不会损失系统的性能。但是在某些特殊的业务下,由于对象的数量太多,采用面向对象会给系统带来难以承受的内存开销.示例代码如下:

            /// <summary>
            /// Word文字的Font样式
            /// </summary>
            public class Font //8+8(继承object的虚表指针4个字节、垃圾收集同步占4个字节)=16个字节
            {
                public Font(string fontName, int size)
                {
                    _fontName = fontName;
                    _size = size;
                }
                string _fontName;//4个字节,但是由于字符串留用技术,可能实际创建大量这个对象的时候,可能会节省一些空间
                int _size;//4个字节
            }
    
            /// <summary>
            /// Word文字对象
            /// </summary>
            public class Charactor //2+4(Font类型的引用指针)+16+2(32位操作系统的内存补齐)+8个字节(继承object的虚表指针4个字节、垃圾收集同步占4个字节)=32个字节
            {
                public Charactor(char c, Font font)
                {
                    _c = c;
                    _font = font;
                }
                char _c;//为一个Unicode字符,16位,占2个字节
                Font _font;//16个字节
            }

    调用代码如下:

            public class ThirdSystem
            {
                public void Run()
                {
    
                    long a = GC.GetTotalMemory(true);
                    //创建10000000个Charactor对象大概要消耗32*10000000/1024/1024=343M
                    int num = 10000000;
                    //创建1千万个Charactor对象
                    var list = new List<Charactor>();//不消耗内存,如果使用ArrayList并指定初始化长度,会产生内存消耗
                    for (var i = 0; i < num; i++)
                    {
                        Charactor charactor = new Charactor('c', new Font("宋体", 6));
                        list.Add(charactor);
                    }
                    long b = GC.GetTotalMemory(true);
                    long memoryConsume = b - a;
                    Console.WriteLine(memoryConsume / 1024 / 1024);//实际输出369,实际创建10000000个Charactor对象消耗了369M的内存空间
                }
            }

    在客户端系统生成了一千万个对象实例,最后产生了369M的内存开销,还单单是一个对象的实例的开销,这种方式显然不可取.

    2、问题

    采用对象方法来创建大量的对象实例,产生了很高的运行时代价-主要指内存方面的,那么如何在采用面向对象的方式生成大量对象实例的同时,避免这种开销呢?

    关于这个问题,字符串留用池的实现方式.提供了很好的借鉴.关于具体实现思路,请参考字符串留用与字符串池

    3、解决方案

    4、使用Flyweight享元模式的要点

    (1)、该模式不涉及抽象性问题,也就是和抽象无关,它主要是解决面向对象的代价问题,在面向对象的过程中,创建了大量的对象实例,所产生的内存消耗.

    (2)、该模式采用共享对象实例的方式来降低系统中对象的个数,也就是通过Hashtable等持有相同对象的引用降低细粒度对象实例带给系统的压力

    (3)、因为采用持有相同对象引用的方式来共享对象,所以当一个对象发生改变时,所有的对象都会发生改变,类似数组,所以要注意对象状态的处理,不能盲目的修改.

    (4)、该模式最好计算下整个系统的开销,在根据实际情况去判断是否要采用享元模式.

  • 相关阅读:
    一起做一款开源软件吧--开源软件诞生1
    牛客-紫魔法师(仙人掌染色-判奇环)
    牛客编程巅峰赛S1第12场 王者C-椭圆曲线(快速乘的运用)
    牛客编程巅峰赛S1第12场 王者B-上上下下(DP)
    牛客编程巅峰赛S1第12场 王者A-锻炼身体(树上追击问题)
    CSUSTOJ 1127-区间方差(线段树)
    Codeforces 1398C- Good Subarrays(区间值为0的个数变形-思维)
    CSUSTOJ 4000-你真的会数据结构吗?(状压+素数分解)
    牛客练习赛67 F-牛妹的苹果树(树上最远点对/区间带权直径-线段树+LCA)
    牛客练习赛67 E-牛妹游历城市(拆位最短路)
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/9823686.html
Copyright © 2011-2022 走看看