Flyweight 享元模式(结构型模式)

面向对象的代价

面向对象很好的解决了系统抽象性的问题,同时在大多数情况下也不会损及系统的性能。但是,在某些特殊应用中,由于对象的数量太大,采用面向对象会给系统带来难以承受的内存开销。比如图形应用中的图元等对象、字处理应用中的字符对象等。

动机(Motivation)

采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,而带来很高的运行代价——主要指内存需求方面的代价。

如何避免大量细粒度对象问题的同时,让外部客户程序仍然能够透明地使用面向对象方式进行操作?

意图(Intent)

运用共享技术有效地支持大量细粒度的对象——《设计模式》GoF

    class Font//(4+4+4)bytes+8bytes=20bytes (8bytes:4bytes垃圾回收控制位,4bytes虚表指针)
{
public string fontName;//4bytes 只是举例子,实际中应该用属性的
public int size;//4bytes
public Color color;//4bytes
        public Font(string fontName,int size,Color color)
        {
            this.fontName = fontName;
            this.size = size;
            this.color = color;
        }
}
/*
4:string fontName,字符串比较特殊,由于已经用了字符串池,就不考虑它在堆中的大小,这里只计算了它的指针大小。
4:int size
4:Color color
8:4bytes垃圾回收控制位+4bytes虚表指针
共20bytes
*/ class Charactor//(2+4+20+2)bytes+8bytes=36bytes
{
pubic char chr;//2bytes
pubic Font font;//20bytes
}
/*
2:char chr
4:Font font,指针占4bytes
20:Font font 堆中大小
2:32位系统的4bytes填充效应,char chr只占2bytes,补充了2bytes
8:4bytes垃圾回收控制位+4bytes虚表指针
共36bytes
*/ class System
{
public static void Main()
{ List<Charactor> list=new List<Charactor>();
for (int i = ; i < ; i++)
{
Charactor charactor=new Charactor();
list.Add(charactor);
}
//36bytes*100000=3600000bytes≈3600k≈3.6M
//如果是1千万个对象结果就是大约360M,这就太大了,要考虑享元模式。
}
}

当Charactor 对象个数非常多时,就考虑使用享元模式了。需要对Charactor 进行改造:

    class Charactor
{
public char chr;
private Font font;
private static Dictionary<string,Font> dicFont; public Font CFunt
{
get { return font; }
set
{
string key = value.fontName + value.size + value.color; if (dicFont.Keys.Contains(key))
{
this.font = dicFont[key];
}
else
{
dicFont.Add(key, value);
this.font = value;
}
}
}
}

这样当出现重复的字体的时候就不会占用多余的空间了。

            Charactor c1=new Charactor();
Font f1= new Font("宋体", , Color.Red);
c1.CFunt = f1; Charactor c2 = new Charactor();
Font f2 = new Font("宋体", , Color.Red);
c2.CFunt = f2;

f1和f2是不同对象,它们指向不同的内存地址,但是在给c1,和c2的CFont赋值时,由于用了Dictionary<string,Font>,对c2的CFont就没有分配新的内存空间。当对象非常多的时候,这样可以节省很多的空间。

.NET中字符串池就是运用了享元模式。

Flyweight模式的几个要点

  • 面向对象很好地解决了抽象性的问题,但是作为一个运行在机器中的程序实体,我们需要考虑对象的代价问题。Flyweight设计模式主要解决面向对象的代价问题,一般不触及面向对象的抽象性问题。
  • Flyweight采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。
  • 对象的数量太大从而导致对象内存开销加大——什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能凭空臆断。

最新文章

  1. sublime Text3及其插件的使用
  2. android 调用电话功能
  3. 【转】CDH5.x升级
  4. web2py--------------用web2py写 django的例子 --------建立一个投票应用(1)
  5. php下载远程图片方法总结(curl手动解析header)curl跳转问题解决
  6. MySQL创建用户权限结果Trigger失败
  7. Babylon.GUI官方文档翻译
  8. GameFreamWork框架----事件系统的应用
  9. 关于vue2.0+hbuilder打包移动端app之后空白页面的解决方案
  10. 网络模型 —— OSI七层模型,TCP五层模型,以及区分
  11. P1160 队列安排 luogu洛谷
  12. 【Django】ORM操作MySQL数据库遇到的一些问题
  13. OSX - libc++究竟是啥?
  14. Java 日期加减
  15. ETL 脚本任务
  16. 使用 Build Pipeline View 插件图表展示Jenkins job依赖关系
  17. TCP状态切换流程
  18. 牛客练习赛28-B(线段树,区间更新)
  19. Safari无痕模式下,storage被禁用问题
  20. 创建Oracle synonym 详解

热门文章

  1. 【ecmall】解决无法上传店铺logo和banner照片问题 (转)
  2. The type javax.xml.rpc.ServiceException cannot be resolved.It is indirectly
  3. 环境无法创建目录,提示Too many links
  4. Jvm垃圾回收器详细
  5. jinja2的一些用法
  6. 1110 Complete Binary Tree
  7. ATM:模拟实现一个ATM + 购物商城程序
  8. php代码优化 -- array_walk 和 foreach, for 的效率的比较
  9. python&#39;s twenty-fifth day for me 模块
  10. 01_java之基本语法