講解C#設(shè)計模式編程中享元模式的運用
一、概述
在軟件開發(fā)中,我們有時需要創(chuàng)建大量細(xì)粒度的對象,比如文檔處理系統(tǒng)就可能需要創(chuàng)建成千上萬的字符對象。但如果對每個字符對象都分配內(nèi)存,那么在系統(tǒng)運行時就會耗費大量的內(nèi)存。如何在保留面向?qū)ο蟛僮鞣绞絻?yōu)點的同時避免創(chuàng)建大量的對象呢?這就到了享元模式發(fā)揮作用的時候了。
二、享元模式
享元模式運用共享技術(shù)有效地支持大量細(xì)粒度的對象。例如可以對文檔處理系統(tǒng)創(chuàng)建共享池,在共享池中建立字母和代碼的對應(yīng)關(guān)系,這樣就可以用共享池中的26個對象解決需要創(chuàng)建大量對象的問題。其結(jié)構(gòu)圖如下:
Flyweight定義了享元接口,外部對象通過這個接口來訪問具體的享元對象。
ConcreteFlyweight實現(xiàn)Flyweight接口,定義了具體的享元對象,并保存享元對象的內(nèi)部狀態(tài)。該享元對象是可共享的。
UnsharedConcreteFlyweight實現(xiàn)Flyweight接口,定義了不用于共享的享元對象。
FlyweightFactory創(chuàng)建并管理享元對象。
Client保存對享元接口的引用,通過該引用有效的使用具體的享元對象。
三、示例
下面以一個實際的應(yīng)用來實現(xiàn)下享元模式。這個例子是:一個文本編輯器中會出現(xiàn)很多字面,使用享元模式去實現(xiàn)這個文本編輯器的話,會把每個字面做成一個享元對象。享元對象的內(nèi)部狀態(tài)就是這個字面,而字母在文本中的位置和字體風(fēng)格等其他信息就是它的外部狀態(tài)。下面就以這個例子來實現(xiàn)下享元模式,具體實現(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)建的對象A
Flyweight fa = factory.GetFlyweight("A");
if (fa != null)
{
// 把外部狀態(tài)作為享元對象的方法調(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");
// 這時候就需要創(chuàng)建一個對象并放入駐留池中
ConcreteFlyweight d = new ConcreteFlyweight("D");
factory.flyweights.Add("D", d);
}
Console.Read();
}
}
/// <summary>
/// 享元工廠,負(fù)責(zé)創(chuàng)建和管理享元對象
/// </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)
{
// 更好的實現(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);
}
// 具體的享元對象,這樣我們不把每個字母設(shè)計成一個單獨的類了,而是作為把共享的字母作為享元對象的內(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>
/// 享元類的實例方法
/// </summary>
/// <param name="extrinsicstate">外部狀態(tài)</param>
public override void Operation(int extrinsicstate)
{
Console.WriteLine("具體實現(xiàn)類: intrinsicstate {0}, extrinsicstate {1}", intrinsicstate, extrinsicstate);
}
}
在享元模式的實現(xiàn)中,我們沒有像之前一樣,把一個細(xì)粒度的類實例設(shè)計成一個單獨的類,而是把它作為共享對象的內(nèi)部狀態(tài)放在共享類的內(nèi)部定義。
四、享元模式的優(yōu)缺點
分析完享元模式的實現(xiàn)之后,讓我們繼續(xù)分析下享元模式的優(yōu)缺點:
優(yōu)點:
降低了系統(tǒng)中對象的數(shù)量,從而降低了系統(tǒng)中細(xì)粒度對象給內(nèi)存帶來的壓力。
缺點:
1.為了使對象可以共享,需要將一些狀態(tài)外部化,這使得程序的邏輯更復(fù)雜,使系統(tǒng)復(fù)雜化。
2.享元模式將享元對象的狀態(tài)外部化,而讀取外部狀態(tài)使得運行時間稍微變長。
五、使用場景
在下面所有條件都滿足時,可以考慮使用享元模式:
- 一個系統(tǒng)中有大量的對象;
- 這些對象耗費大量的內(nèi)存;
- 這些對象中的狀態(tài)大部分都可以被外部化;
- 這些對象可以按照內(nèi)部狀態(tài)分成很多的組,當(dāng)把外部對象從對象中剔除時,每一個組都可以僅用一個對象代替;
- 軟件系統(tǒng)不依賴這些對象的身份。
滿足上面的條件的系統(tǒng)可以使用享元模式。但是使用享元模式需要額外維護(hù)一個記錄子系統(tǒng)已有的所有享元的表,而這也需要耗費資源,所以,應(yīng)當(dāng)在有足夠多的享元實例可共享時才值得使用享元模式。
欄 目:C#教程
下一篇:c#檢測文本文件編碼的方法
本文標(biāo)題:講解C#設(shè)計模式編程中享元模式的運用
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/6673.html
您可能感興趣的文章
- 01-10C#編程實現(xiàn)自定義熱鍵的方法
- 01-10C#編程獲取資源文件中圖片的方法
- 01-10深入淺出23種設(shè)計模式
- 01-10C#日歷樣式的下拉式計算器實例講解
- 01-10C#編程自學(xué)之?dāng)?shù)據(jù)類型和變量二
- 01-10C#編程自學(xué)之開篇介紹
- 01-10C#編程自學(xué)之?dāng)?shù)據(jù)類型和變量三
- 01-10C#編程自學(xué)之運算符和表達(dá)式
- 01-10C#導(dǎo)出網(wǎng)站功能實例代碼講解
- 01-10C#編程自學(xué)之類和對象


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機閱讀
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-10C#中split用法實例總結(jié)
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-11ajax實現(xiàn)頁面的局部加載


