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采用对象共享的做法来降低系统中对象的个数,从而降低细粒度对象给系统带来的内存压力。在具体实现方面,要注意对象状态的处理。
  • 对象的数量太大从而导致对象内存开销加大——什么样的数量才算大?这需要我们仔细的根据具体应用情况进行评估,而不能凭空臆断。

设计模式11: Flyweight 享元模式(结构型模式)的更多相关文章

  1. Flyweight 享元(结构型)

    一:描述:(该模式实际应用较少) Flyweight 享元模式是对大量细粒度的元素进行共享和重用.减少对象的创建减轻内存: 注和单例模式不同的是:享元模式的各个对象佣有各自的行为并可实例化,单例模式的 ...

  2. 设计模式(11)--Flyweight(享元模式)--结构型

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 1.模式定义: 享元模式是对象的结构模式.享元模式以共享的方式高效地支持大量的细粒度对象. 2.模式特点: 享元模 ...

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

    说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释放.我们只是为了学习而简单做了介绍. 1. 概述 面 ...

  4. 面向对象设计模式之Flyweight享元模式(结构型)

    动机:采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行代价——主要指内存需求方面的代价.如何在避免大量细粒度对象问题的同 时,让外部客户程序仍然能够透明地使用面向对象的 ...

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

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

  6. 设计模式之flyweight享元模式

    运用共享技术支持大量细粒度对象的使用 Flyweight模式(享元) Java深入到一定程度,就不可避免的碰到设计模式这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模 ...

  7. (转)Java经典设计模式(2):七大结构型模式(附实例和详解)

    原文出处: 小宝鸽 总体来说设计模式分为三大类:创建型模式.结构型模式和行为型模式. 博主的上一篇文章已经提到过创建型模式,此外该文章还有设计模式概况和设计模式的六大原则.设计模式的六大原则是设计模式 ...

  8. 设计模式06: Adapter 适配器模式(结构型模式)

    Adapter 适配器模式(结构型模式) 适配(转换)的概念无处不在:电源转接头.电源适配器.水管转接头... 动机(Motivation)在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象 ...

  9. 设计模式09: Decorator 装饰模式(结构型模式)

    Decorator 装饰模式(结构型模式) 子类复子类,子类何其多加入我们需要为游戏中开发一种坦克,除了不同型号的坦克外,我们还希望在不同场合中为其增加以下一种多种功能:比如红外线夜视功能,比如水路两 ...

  10. 代理模式/proxy模式/结构型模式

    代理模式proxy 定义 为其他对象提供一种代理,并以控制对这个对象的访问.最简单的理解,买东西都是要去商店的,不会去工厂. java实现三要素 proxy(代理)+subject(接口)+realS ...

随机推荐

  1. (转)java.lang.RuntimeException: Missing type parameter

    java.lang.RuntimeException: Missing type parameter (2015-04-07 14:35:51)   分类: 技术 程序中用到了gson的new typ ...

  2. Java基础知识复习(一)

    - JVM内存区域 程序计数器:一个比较小的内存区域,用于指示当前线程所执行的字节码执行到了第几行,是线程隔离的. Java虚拟机栈:Java方法执行的内存模型,用于存储局部变量,操作数栈,动态链接, ...

  3. Ajax验证用户名

    用Ajax验证用户名: 接口: get guestbook/index.php m : index a : verifyUserName username : 要验证的用户名 返回 { code : ...

  4. MVC FileDownLoad

    public ActionResult MatDownload() { string ShopId = Session["ShopId"].ToString(); var self ...

  5. ALTERA DDRII IP核使用

    提到DDRII,大家应该都不陌生,DDRII SDRAM是第二代双倍速率同步动态RAM.今天小编给大家介绍一下QUARTUS II 下调用DDRII软核. 新建QUARTUSII工程之后,在tool下 ...

  6. HEALTH_WARN too few PGs per OSD (21 < min 30)解决方法

    标签(空格分隔): ceph,ceph运维,pg 集群环境: [root@node3 ~]# cat /etc/redhat-release CentOS Linux release 7.3.1611 ...

  7. MyBatis 工具 pndao - 自动写 SQL

    pndao的原理并不复杂,是基于MyBatis的方法命名约定来生成SQL,并且写入MyBatis需要的XML. 写之前会判断是否已经存在XML或者注解,如果已经存在则略过此方法,所以无论是注解还是XM ...

  8. IDA Pro 权威指南学习笔记(七) - 其他 IDA 显示窗口

    默认情况下 IDA 不会打开这些窗口,可通过 View -> Open Subviews 命令打开 Strings 窗口(Strings) Strings 窗口中显示的是从二进制文件中提取出的一 ...

  9. springboot成神之——spring boot,spring jdbc和spring transaction的使用

    本文介绍spring boot,spring jdbc和spring transaction的使用 项目结构 依赖 application model层 mapper层 dao层 exception层 ...

  10. temp3