欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

講解C#設(shè)計(jì)模式編程中享元模式的運(yùn)用

 更新時(shí)間:2016年02月22日 09:17:34   投稿:goldensun  
這篇文章主要介紹了C#設(shè)計(jì)模式編程中享元模式的運(yùn)用,享元模式主張限制對(duì)象的數(shù)量來優(yōu)化內(nèi)存使用,需要的朋友可以參考下

一、概述

在軟件開發(fā)中,我們有時(shí)需要?jiǎng)?chuàng)建大量細(xì)粒度的對(duì)象,比如文檔處理系統(tǒng)就可能需要?jiǎng)?chuàng)建成千上萬的字符對(duì)象。但如果對(duì)每個(gè)字符對(duì)象都分配內(nèi)存,那么在系統(tǒng)運(yùn)行時(shí)就會(huì)耗費(fèi)大量的內(nèi)存。如何在保留面向?qū)ο蟛僮鞣绞絻?yōu)點(diǎn)的同時(shí)避免創(chuàng)建大量的對(duì)象呢?這就到了享元模式發(fā)揮作用的時(shí)候了。

二、享元模式

享元模式運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對(duì)象。例如可以對(duì)文檔處理系統(tǒng)創(chuàng)建共享池,在共享池中建立字母和代碼的對(duì)應(yīng)關(guān)系,這樣就可以用共享池中的26個(gè)對(duì)象解決需要?jiǎng)?chuàng)建大量對(duì)象的問題。其結(jié)構(gòu)圖如下:

201622291612761.jpg (467×289)

Flyweight定義了享元接口,外部對(duì)象通過這個(gè)接口來訪問具體的享元對(duì)象。

ConcreteFlyweight實(shí)現(xiàn)Flyweight接口,定義了具體的享元對(duì)象,并保存享元對(duì)象的內(nèi)部狀態(tài)。該享元對(duì)象是可共享的。

UnsharedConcreteFlyweight實(shí)現(xiàn)Flyweight接口,定義了不用于共享的享元對(duì)象。

FlyweightFactory創(chuàng)建并管理享元對(duì)象。

Client保存對(duì)享元接口的引用,通過該引用有效的使用具體的享元對(duì)象。

三、示例
下面以一個(gè)實(shí)際的應(yīng)用來實(shí)現(xiàn)下享元模式。這個(gè)例子是:一個(gè)文本編輯器中會(huì)出現(xiàn)很多字面,使用享元模式去實(shí)現(xiàn)這個(gè)文本編輯器的話,會(huì)把每個(gè)字面做成一個(gè)享元對(duì)象。享元對(duì)象的內(nèi)部狀態(tài)就是這個(gè)字面,而字母在文本中的位置和字體風(fēng)格等其他信息就是它的外部狀態(tài)。下面就以這個(gè)例子來實(shí)現(xiàn)下享元模式,具體實(shí)現(xiàn)代碼如下:

/// <summary>
 /// 客戶端調(diào)用
 /// </summary>
 class Client
 {
  static void Main(string[] args)
  {
   // 定義外部狀態(tài),例如字母的位置等信息
   int externalstate = 10;
   // 初始化享元工廠
   FlyweightFactory factory = new FlyweightFactory();
   // 判斷是否已經(jīng)創(chuàng)建了字母A,如果已經(jīng)創(chuàng)建就直接使用創(chuàng)建的對(duì)象A
   Flyweight fa = factory.GetFlyweight("A");
   if (fa != null)
   {
    // 把外部狀態(tài)作為享元對(duì)象的方法調(diào)用參數(shù)
    fa.Operation(--externalstate);
   }
   // 判斷是否已經(jīng)創(chuàng)建了字母B
   Flyweight fb = factory.GetFlyweight("B");
   if (fb != null)
   {
    fb.Operation(--externalstate);
   }
   // 判斷是否已經(jīng)創(chuàng)建了字母C
   Flyweight fc = factory.GetFlyweight("C");
   if (fc != null)
   {
    fc.Operation(--externalstate);
   }
   // 判斷是否已經(jīng)創(chuàng)建了字母D
   Flyweight fd= factory.GetFlyweight("D");
   if (fd != null)
   {
    fd.Operation(--externalstate);
   }
   else
   {
    Console.WriteLine("駐留池中不存在字符串D");
    // 這時(shí)候就需要?jiǎng)?chuàng)建一個(gè)對(duì)象并放入駐留池中
    ConcreteFlyweight d = new ConcreteFlyweight("D");
    factory.flyweights.Add("D", d);
   }
   Console.Read();
  }
 }
 /// <summary>
 /// 享元工廠,負(fù)責(zé)創(chuàng)建和管理享元對(duì)象
 /// </summary>
 public class FlyweightFactory
 {
  // 最好使用泛型Dictionary<string,Flyweighy>
  //public Dictionary<string, Flyweight> flyweights = new Dictionary<string, Flyweight>();
  public Hashtable flyweights = new Hashtable();
  public FlyweightFactory()
  {
   flyweights.Add("A", new ConcreteFlyweight("A"));
   flyweights.Add("B", new ConcreteFlyweight("B"));
   flyweights.Add("C", new ConcreteFlyweight("C"));
  }
  public Flyweight GetFlyweight(string key)
  {
// 更好的實(shí)現(xiàn)如下
   //Flyweight flyweight = flyweights[key] as Flyweight;
   //if (flyweight == null)
   //{
   // Console.WriteLine("駐留池中不存在字符串" + key);
   // flyweight = new ConcreteFlyweight(key);
   //}
   //return flyweight;
return flyweights[key] as Flyweight;
  }
 }
 /// <summary>
 /// 抽象享元類,提供具體享元類具有的方法
 /// </summary>
 public abstract class Flyweight
 {
  public abstract void Operation(int extrinsicstate);
 }
 // 具體的享元對(duì)象,這樣我們不把每個(gè)字母設(shè)計(jì)成一個(gè)單獨(dú)的類了,而是作為把共享的字母作為享元對(duì)象的內(nèi)部狀態(tài)
 public class ConcreteFlyweight : Flyweight
 {
  // 內(nèi)部狀態(tài)
  private string intrinsicstate ;
  // 構(gòu)造函數(shù)
  public ConcreteFlyweight(string innerState)
  {
   this.intrinsicstate = innerState;
  }
  /// <summary>
  /// 享元類的實(shí)例方法
  /// </summary>
  /// <param name="extrinsicstate">外部狀態(tài)</param>
  public override void Operation(int extrinsicstate)
  {
   Console.WriteLine("具體實(shí)現(xiàn)類: intrinsicstate {0}, extrinsicstate {1}", intrinsicstate, extrinsicstate);
  }
 }

在享元模式的實(shí)現(xiàn)中,我們沒有像之前一樣,把一個(gè)細(xì)粒度的類實(shí)例設(shè)計(jì)成一個(gè)單獨(dú)的類,而是把它作為共享對(duì)象的內(nèi)部狀態(tài)放在共享類的內(nèi)部定義。

四、享元模式的優(yōu)缺點(diǎn)
分析完享元模式的實(shí)現(xiàn)之后,讓我們繼續(xù)分析下享元模式的優(yōu)缺點(diǎn):

優(yōu)點(diǎn):

降低了系統(tǒng)中對(duì)象的數(shù)量,從而降低了系統(tǒng)中細(xì)粒度對(duì)象給內(nèi)存帶來的壓力。

缺點(diǎn):

1.為了使對(duì)象可以共享,需要將一些狀態(tài)外部化,這使得程序的邏輯更復(fù)雜,使系統(tǒng)復(fù)雜化。
2.享元模式將享元對(duì)象的狀態(tài)外部化,而讀取外部狀態(tài)使得運(yùn)行時(shí)間稍微變長(zhǎng)。


五、使用場(chǎng)景
在下面所有條件都滿足時(shí),可以考慮使用享元模式:

  • 一個(gè)系統(tǒng)中有大量的對(duì)象;
  • 這些對(duì)象耗費(fèi)大量的內(nèi)存;
  • 這些對(duì)象中的狀態(tài)大部分都可以被外部化;
  • 這些對(duì)象可以按照內(nèi)部狀態(tài)分成很多的組,當(dāng)把外部對(duì)象從對(duì)象中剔除時(shí),每一個(gè)組都可以僅用一個(gè)對(duì)象代替;
  • 軟件系統(tǒng)不依賴這些對(duì)象的身份。

滿足上面的條件的系統(tǒng)可以使用享元模式。但是使用享元模式需要額外維護(hù)一個(gè)記錄子系統(tǒng)已有的所有享元的表,而這也需要耗費(fèi)資源,所以,應(yīng)當(dāng)在有足夠多的享元實(shí)例可共享時(shí)才值得使用享元模式。

相關(guān)文章

最新評(píng)論