.Net結(jié)構(gòu)型設(shè)計模式之享元模式(Flyweight)
一、動機(jī)(Motivate)
在軟件系統(tǒng)中,采用純粹對象方案的問題在于大量細(xì)粒度的對象會很快充斥在系統(tǒng)中,從而帶來很高的運(yùn)行時代價——主要指內(nèi)存需求方面的代價。如何在避免大量細(xì)粒度對象問題的同時,讓外部客戶程序仍然能夠透明地使用面向?qū)ο蟮姆绞絹磉M(jìn)行操作?
二、意圖(Intent)
運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對象。 ——《設(shè)計模式》GoF
三、結(jié)構(gòu)圖(Structure)
四、模式的組成
(1)、抽象享元角色(Flyweight):此角色是所有的具體享元類的基類,為這些類規(guī)定出需要實(shí)現(xiàn)的公共接口。那些需要外部狀態(tài)的操作可以通過調(diào)用方法以參數(shù)形式傳入。
(2)、具體享元角色(ConcreteFlyweight):實(shí)現(xiàn)抽象享元角色所規(guī)定的接口。如果有內(nèi)部狀態(tài)的話,可以在類內(nèi)部定義。
(3)、享元工廠角色(FlyweightFactory):本角色負(fù)責(zé)創(chuàng)建和管理享元角色。本角色必須保證享元對象可以被系統(tǒng)適當(dāng)?shù)毓蚕?,?dāng)一個客戶端對象調(diào)用一個享元對象的時候,享元工廠角色檢查系統(tǒng)中是否已經(jīng)有一個符合要求的享元對象,如果已經(jīng)存在,享元工廠角色就提供已存在的享元對象,如果系統(tǒng)中沒有一個符合的享元對象的話,享元工廠角色就應(yīng)當(dāng)創(chuàng)建一個合適的享元對象。
(4)、客戶端角色(Client):本角色需要存儲所有享元對象的外部狀態(tài)。
五、享元模式的具體代碼實(shí)現(xiàn)
/// <summary> /// 享元的抽象類 /// </summary> public abstract class Flyweight { public abstract void Operation(int extrinsicState); } /// <summary> /// 需要共享的具體類 /// </summary> public class ConceteFlyweight : Flyweight { public override void Operation(int extrinsicState) { Console.WriteLine("需要共享的具體Flyweight類:" + extrinsicState); } } /// <summary> /// 不需要共享的具體類 /// </summary> public class UnsharedConcreteFlyeight : Flyweight { public override void Operation(int extrinsicState) { Console.WriteLine("不需要共享的具體Flyweight類:" + extrinsicState); } } /// <summary> /// 一個工廠類,用來合理創(chuàng)建對象 /// </summary> public class FlyweightFactory { private Dictionary<string, Flyweight> dic = new Dictionary<string, Flyweight>(); public Flyweight GetFlyweight(string key, bool type) { if (!dic.ContainsKey(key)) { Flyweight flyweight = new UnsharedConcreteFlyeight(); if (type) flyweight = new ConceteFlyweight(); dic.Add(key, flyweight); } return (Flyweight)dic[key]; } } /// <summary> /// 客戶端調(diào)用 /// </summary> public class App { static void Main() { int extrinsicState = 26; FlyweightFactory factory = new FlyweightFactory(); Flyweight f1 = factory.GetFlyweight("oec2003", true); f1.Operation(++extrinsicState); Flyweight f2 = factory.GetFlyweight("oec2003", true); f2.Operation(++extrinsicState); Flyweight f3 = factory.GetFlyweight("oec2004", false); f3.Operation(++extrinsicState); } }
六、享元模式的實(shí)現(xiàn)要點(diǎn):
面向?qū)ο蠛芎玫亟鉀Q了抽象性的問題,但是作為一個運(yùn)行在機(jī)器中的程序?qū)嶓w,我們需要考慮對象的代價問題。Flyweight設(shè)計模式主要解決面向?qū)ο蟮拇鷥r問題,一般不觸及面向?qū)ο蟮某橄笮詥栴}。
Flyweight采用對象共享的做法來降低系統(tǒng)中對象的個數(shù),從而降低細(xì)粒度對象給系統(tǒng)帶來的內(nèi)存壓力。在具體實(shí)現(xiàn)方面,要注意對象狀態(tài)的處理。
對象的數(shù)量太大從而導(dǎo)致對象內(nèi)存開銷加大——什么樣的數(shù)量才算大?這需要我們仔細(xì)的根據(jù)具體應(yīng)用情況進(jìn)行評估,而不能憑空臆斷。
1、享元模式的優(yōu)點(diǎn)
(1)、享元模式的優(yōu)點(diǎn)在于它能夠極大的減少系統(tǒng)中對象的個數(shù)。
(2)、享元模式由于使用了外部狀態(tài),外部狀態(tài)相對獨(dú)立,不會影響到內(nèi)部狀態(tài),所以享元模式使得享元對象能夠在不同的環(huán)境被共享。
2、享元模式的缺點(diǎn)
(1)、由于享元模式需要區(qū)分外部狀態(tài)和內(nèi)部狀態(tài),使得應(yīng)用程序在某種程度上來說更加復(fù)雜化了。
(2)、為了使對象可以共享,享元模式需要將享元對象的狀態(tài)外部化,而讀取外部狀態(tài)使得運(yùn)行時間變化。
3、在下面所有條件都滿足時,可以考慮使用享元模式:
(1)、一個系統(tǒng)中有大量的對象;
(2)、這些對象耗費(fèi)大量的內(nèi)存;
(3)、這些對象中的狀態(tài)大部分都可以被外部化;
(4)、這些對象可以按照內(nèi)部狀態(tài)分成很多的組,當(dāng)把外部對象從對象中剔除時,每一個組都可以僅用一個對象代替軟件系統(tǒng)不依賴這些對象的身份,滿足上面的條件的系統(tǒng)可以使用享元模式。但是使用享元模式需要額外維護(hù)一個記錄子系統(tǒng)已有的所有享元的表,而這也需要耗費(fèi)資源,所以,應(yīng)當(dāng)在有足夠多的享元實(shí)例可共享時才值得使用享元模式。
七、.NET 中享元模式的實(shí)現(xiàn)
.NET在C#中有一個Code Behind機(jī)制,它表面有一個aspx文件,背后又有一個cs文件,它的編譯過程實(shí)際上會把a(bǔ)spx文件解析成C#文件,然后編譯成dll,在這個過程中,我們在aspx中寫的任何html代碼都會轉(zhuǎn)化為literal control,literal control是一個一般的文本控件,它就表示html標(biāo)記。當(dāng)這些標(biāo)記有一樣的時候,構(gòu)建控件樹的時候就會用到Flyweight模式。
它的應(yīng)用并不是那么平凡,只有在效率空間確實(shí)不高的時候我們才用它。
到此這篇關(guān)于.Net結(jié)構(gòu)型設(shè)計模式之享元模式(Flyweight)的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
.Net Core使用SignalR實(shí)現(xiàn)斗地主游戲
本文詳細(xì)講解了.Net Core使用SignalR實(shí)現(xiàn)斗地主游戲的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-01-01Linux?CentOS下docker部署Asp.Net?Core(.Net6)
這篇文章介紹了Linux?CentOS下docker部署Asp.Net?Core(.Net6)的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12搭建基礎(chǔ)結(jié)構(gòu)的ABP解決方案介紹
這篇文章介紹了搭建基礎(chǔ)結(jié)構(gòu)的ABP解決方案的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02.Net中Task Parallel Library的基本用法
這篇文章介紹了.Net中Task Parallel Library的基本用法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-10-10