結構型模式: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)對象的數量太大從而致使對象內存開銷加大——什麼樣的數量纔算大?這須要咱們仔細的根據具體應用狀況進行評估,而不能憑空臆斷。指針

相關文章
相關標籤/搜索