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)、该模式最好计算下整个系统的开销,在根据实际情况去判断是否要采用享元模式.

原文地址:https://www.cnblogs.com/GreenLeaves/p/9823686.html

时间: 2024-08-02 17:09:33

Flyweight享元模式(结构型模式)的相关文章

Flyweight 享元(结构型)

一:描述:(该模式实际应用较少) Flyweight 享元模式是对大量细粒度的元素进行共享和重用.减少对象的创建减轻内存: 注和单例模式不同的是:享元模式的各个对象佣有各自的行为并可实例化,单例模式的各个对象佣有一样的行为并不可直接实例化. 二:模式图: 三:实现代码简单例子: 1.创建抽像的享元类 2.创建共享的享元对象(可以有很多这种对像) 3.创建非共享的享元对象 4.创建享元的工厂 5.客端的使用和效果;

设计模式(十二): Flyweight享元模式 -- 结构型模式

说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面向对象技术可以很好地解决系统一些灵活性或可扩展性或抽象性的问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.比如:例子1:图形应用中的图元等对象.字处理应用中的字符对象等. 2.解决方案: 享元模式(Flyweight):对象结构型模式运用

设计模式(九):Composite组合模式 -- 结构型模式

1. 概述 在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面. 例子1:就是多级树形菜单. 例子2:文件和文件夹目录 2.问题 我们可以使用简单的对象组合成复杂的对象,而这个复杂对象有可以组合成更大的对象.我们可以把简单这些对象定义成类,然后定义一些容器类来存储这些简单对象.客户端代码必须区别对象简单对象和容器对象,而实际上大多数情况下用户认为它们是一样的.对这些类区别使用,使得程序更加复杂.递归使用的时候跟麻烦,而我们如何使用递归组合,使得用户不必对这些类进行区别呢? 3.

设计模式(八):Bridge桥接模式 -- 结构型模式

1. 概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或多个维度的变化,那么如何应对这种“多维度的变化”?如何利用面向对象的技术来使得该类型能够轻松的沿着多个方向进行变化,而又不引入额外的复杂度? 例子1:设想如果要绘制矩形.圆形.椭圆.正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色.绿色.蓝色等,此时至少有如下两种设计方案: •第一种设计方案是为每一种形状都提供一套各种颜色的版本. •第二种设计方案是根据实际需要对形状和颜色进行组合. 方案1: 方案2:  

一起学java设计模式--代理模式(结构型模式)

代理模式 应用软件所提供的桌面快捷方式是快速启动应用程序的代理,桌面快捷方式一般使用一张小图片来表示(Picture),通过调用快捷方式的run()方法将调用应用软件(Application)的run()方法.使用代理模式模拟该过程,绘制类图并编程实现. package ProxyPattern; interface Software { void run(); } class Application implements Software { public void run() { Syste

设计模式(十):Decorator装饰者模式 -- 结构型模式

1. 概述 若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一个基本特性.如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类—这建立在额外的代码上. 通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法.但是这种方法是静态的,用户不能控制增加行为的方式和时机.如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许多类的行为,改怎么办?前一个,只能在于运行时完成,后者

设计模式(十一):FACADE外观模式 -- 结构型模式

1. 概述 外观模式,我们通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性.例子1:一个电源总开关可以控制四盏灯.一个风扇.一台空调和一台电视机的启动和关闭.该电源总开关可以同时控制上述所有电器设备,电源总开关即为该系统的外观模式设计. 2. 问题 为了降低复杂性,常常将系统划分为若干个子系统.但是如何做到各个系统之间的通信和相互依赖关系达到最小呢? 3. 解决方案 外观模式:为子系统中的一组接口提供一个一致的界面,

设计模式(十三): Proxy代理模式 -- 结构型模式

  设计模式(十一)代理模式Proxy(结构型) 1.概述 因为某个对象消耗太多资源,而且你的代码并不是每个逻辑路径都需要此对象, 你曾有过延迟创建对象的想法吗 ( if和else就是不同的两条逻辑路径) ? 你有想过限制访问某个对象,也就是说,提供一组方法给普通用户,特别方法给管理员用户?以上两种需求都非常类似,并且都需要解决一个更大的问题:你如何提供一致的接口给某个对象让它可以改变其内部功能,或者是从来不存在的功能? 可以通过引入一个新的对象,来实现对真实对象的操作或者将新的对象作为真实对象

Proxy代理模式(结构型模式)

1.问题 在面向对象系统中,有些对象由于某种原因(比如创建对象的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给调用者带来麻烦,那么如何在不损失接口透明性的情况下,解决这些麻烦? 2.解决方案 通过架设一层中间层,让这层中间层来解决上面的麻烦,也就是我们所说的代理.大致的结构转换图如下: 转换成 将一个复杂的系统A,通过假设一层中间层C,将A中的复杂度处理掉,并通过C向B提供一种更灵活,满足B需求的方案. 案例一..Net中WebService技术提供了很好的借鉴.代码