结构型模式:Flyweight 享元模式

                                                   结构型模式:Flyweight 享元模式

1、面向对象的代价
  1)面向对象很好地解决了系统抽象性的问题,同时在大多数状况下,也不会损及系统的性能。可是,在某些特殊的应用中,因为对象的数量太大,采用面向对象会给系统带来难以承受的内存开销。好比图形应用中的图元等对象、字处理应用中的字符对象等。
 
2、动机(Motivation)
  1)采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价——主要指内存需求方面的代价。
  2)如何在避免大量细粒对象问题的同时,让外部客户程序仍然可以透明地使用面向对象的方式来进行操做?
 
3、意图(Intent)
  运用共享技术有效地支持大量细粒度的对象。
                                                                    ——《设计模式》GoF
 
4、实例:每个字符都应用一种字体
  1)常规作法
//本身实如今一个Font
//Font对象占用内存(4+4+4(三个字段可见))+ (4+4(虚表指针、同步垃圾回收指针不可见))= 20bytes * n
public class Font
{
  private string fontName;//一个指针占 4bytes
  private int size;       //整形int占 4bytes
  private Color color;     //对象也是指针占4bytes
}设计模式

//考虑这个对象的大小,它是细粒度的对象
//Charactor对象战用内存(2+4+20+2(有一个内存对齐填充的效应))+(4+4) = 36bytes
public class Charactor
{
  private char c;//字符占16 bit, 2bytes //有一个内存对齐填充的效应
  private Font f;//字符类型占20bytes 指针占4bytes
}ide

//客户
class System
{
  public static void Main
  {
    //36bytes*100000=3600000 bytes =(3600k)-->3M数据
    //若是是10000000个对象就占用300M数据了
    ArrayList list = new ArrayList(100000);
    for (int i = 0; i < list.Count; i++)
    {
      //这个字符对象不必定要new,有可能经过其余方式获得,好比序列化
      Charactor c = new Charactor();
      list.Add(c);
    }
  }
}性能

  2)就用Flyweight模式共享Font对象的内存空间
public class Font
{
  private string fontName;
  private int size;      
  private Color color;
  //重写Font.Equals()方法
  public override bool Equals(Font font)
  {
  }   
}字体

public class Charactor
{
  private char c;
  private Font f;
  //保存已存在的字体对象
  //这里能够抽象出一个简单的工厂模式,动态获得存在的font
  private static Hashtable fontTable = new Hashtable();
 
  public char Chr
  {
    get
    {
      return c;
    }
    set
    {
      c = value;
    }
  }
 
  public Font CFont
  {
    get
    {
      return f;
    }
    set
    {
      //在设置字体时,若是已经有了这个字体对象,咱们就不须要new了
      //只须要将指针指向已经存在的这个字体对象
      if (fontTable.Keys.Exist(f))
      {
        this.f = fontTable.Keys[f];
      }
      else
      {
        fontTable.Keys.Add(f);
        this.f = value;
      }
    }
  }
}this

//客户
class System
{
  public static void Main
  {
    ArrayList list = new ArrayList(100000);
   
    Font f1 = new Font("宋体", 5, Color.Red);
    Font f2 = new Font("宋体", 5, Color.Red);
   
    Charactor c1 = new Charactor();
    c1.Chr = 'a';
    c1.CFont = f1;
   
    Charactor c2 = new Charactor();
    c2.Chr = 'a';
    c2.CFont = f2;
    //c2应用的字体对象指向的同一块内存空间
  }
}设计

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

相关文章
相关标签/搜索