最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入C#字符串和享元(Flyweight)模式的使用分析

 更新時間:2013年05月15日 16:00:27   投稿:jingxian  
本篇文章是對C#字符串與享元(Flyweight)模式的使用進行了詳細的分析介紹,需要的朋友參考下

寫這個文章,主要是因為網(wǎng)上對C#字符串和享元模式的誤解比較多。

Flyweight模式
先說這名字,fly呢,就是蒼蠅,沒錯這里面不是飛的意思,是蒼蠅的意思,weight大家都知道,就是重量,蒼蠅的重量,就是非常非常輕的意思。所以Flyweight模式就是處理非常非常輕量級對象的一個東西。
Flyweight的目標是解決大量細粒度對象的內(nèi)存消耗問題,當然,巧婦難為無米之炊,任何模式和手法都不能憑空造出內(nèi)存來,所以享元模式針對的情況是這些細粒度對象的中數(shù)據(jù)有重復的情況。
Flyweight的做法是,把對象的狀態(tài)(通常用屬性表示),分成兩個部分,一部分是內(nèi)部狀態(tài),另一部分是外部狀態(tài)。內(nèi)部狀態(tài)外部狀態(tài)是不易重復的(或者說必要的),外部狀態(tài) 內(nèi)部狀態(tài)是易重復的。所以,F(xiàn)lyweight把外部狀態(tài)提取出來共享,這樣就一定程度解決了內(nèi)存占用問題。

C#中的字符串不是Flyweight模式
在網(wǎng)上常常可以看到一個說法,說C#中的字符串使用了Flyweight模式,開門見山地說,這個說法是錯誤的。
錯在哪里呢?按照上文的介紹,錯就錯在字符串它沒有所謂的“內(nèi)部狀態(tài)外部狀態(tài)”。
通常講字符串是享元的原因就是以下代碼:
string a = "Hello World";
Console.WriteLine(Object.ReferenceEquals(a, "Hello World")); //True
當使用字符串直接量的時候,不論你寫了多少個"Hello World",最終內(nèi)存里面只有一個字符串對象。
運行時創(chuàng)建的字符串并不在此列,可以使些手段,強制在內(nèi)存里面產(chǎn)生新的字符串。
string a = "Hello World";
Console.WriteLine(Object.ReferenceEquals(a, new String("Hello World".ToCharArray())));  //False
因為我們強行調(diào)用了new,所以這個字符串跟內(nèi)存中的直接量"Hello World"對應的對象不是同一個。
有趣的是,C#還允許強制把一個字符串加入到(如果已經(jīng)有了,就只是找出來)字符串池里面。
string a = "Hello World";
string b = String.Intern(new String("Hello World".ToCharArray()));
Console.WriteLine(Object.ReferenceEquals(a,b) );   
或者
string a = String.Intern(new String("Hello World".ToCharArray()));
string b = String.Intern(new String("Hello World".ToCharArray()));
Console.WriteLine(Object.ReferenceEquals(a,b) );
前面提到了,這個行為跟Flyweight使用的內(nèi)部狀態(tài)和外部狀態(tài)不同,是兩個對象實實在在就是同一個對象。

C#中的字符串與Flyweight模式
好吧,前面說了不少,C#中的字符串不是Flyweight模式,但是是不是就意味著C#里面字符串跟Flyweight沒有關(guān)系呢?
字符串池和Intern方法簡直是實現(xiàn)Flyweight的神器??!
考慮我們有某一類對象,可能會創(chuàng)建幾百萬個,對象里面恰巧有這么一個屬性叫做顏色,它在對象構(gòu)造的時候隨機產(chǎn)生,顏色用的是rgb色,用rgb24來表示,于是顏色字符串類似#ccc這樣子。
代碼寫起來就像下面的樣子:

復制代碼 代碼如下:

    class Element
    {
 static Random rnd = new Random();
 static char[] table;
 static Element()
 {
     table = "0123456789abcdef".ToCharArray();
 }
 public string color;
 public Element()
 {
     color = "" + table[rnd.Next() % 16] + table[rnd.Next() % 16] + table[rnd.Next() % 16];
 }
    }

接下來我們創(chuàng)建3千萬個對象看看如何
復制代碼 代碼如下:

     Element[] eles = new Element[30000000];
     for (var i = 0; i < 30000000; i++)
     {
  eles[i] = new Element();
     }

從任務管理器看到一大塊內(nèi)存被吃掉了

QFOMR9}(NR%(T3`V3Q35MSY

接下來我們使用String.Intern來實現(xiàn)Flyweight:

復制代碼 代碼如下:

    class Element
    {
 static Random rnd = new Random();
 static char[] table;
 static Element()
 {
     table = "0123456789abcdef".ToCharArray();
 }

 public string color;
 public Element()
 {
     color = String.Intern("" + table[rnd.Next() % 16] + table[rnd.Next() % 16] + table[rnd.Next() % 16]);
 }
    }


可以看到內(nèi)存占用量的明顯變化。
因為字符串對象的不可更改性質(zhì),使用了String.Intern之后,我們完全看不出前后color的區(qū)別,也就是說,修改前后的Element類是完全等效的,但是Flyweight為我們節(jié)約了大量的內(nèi)存。

更多思考
這個典型的使用flyweight場景為我們揭示了享元外部狀態(tài)內(nèi)部狀態(tài)的特征:像字符串一樣不可更改的對象。GoF原書的例子中的字型對象Glyph也是如此。
String.Intern這種對象池的方式實現(xiàn)flyweight也值得借鑒,我們可以考慮自己設計flyweight的外部狀態(tài)對象時使用類似的方式。

相關(guān)文章

  • c# 值類型實例構(gòu)造器

    c# 值類型實例構(gòu)造器

    CLR總是允許創(chuàng)建值類型的實例。另外值類型不一定需要定義構(gòu)造器,c#編譯器不會為值類型生成默認的無參構(gòu)造器
    2012-10-10
  • C# WinForm程序設計簡單計算器

    C# WinForm程序設計簡單計算器

    這篇文章主要為大家詳細介紹了C# WinForm程序設計簡單計算器,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • c#下將.cs文件編譯成dll

    c#下將.cs文件編譯成dll

    c#下將.cs文件編譯成dll...
    2007-07-07
  • C#中DropDownList動態(tài)生成的方法

    C#中DropDownList動態(tài)生成的方法

    這篇文章主要介紹了C#中DropDownList動態(tài)生成的方法,實例分析了C#中DropDownList的使用技巧,非常具有實用價值,需要的朋友可以參考下
    2015-03-03
  • C#中Shear的用法實例

    C#中Shear的用法實例

    這篇文章主要介紹了C#中Shear的用法,實例分析了C#中使用Matrix實現(xiàn)Shear剪切變換的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • C#數(shù)據(jù)庫操作的用法

    C#數(shù)據(jù)庫操作的用法

    這篇文章主要介紹了C#數(shù)據(jù)庫操作的三種經(jīng)典用法
    2015-10-10
  • C#利用QrCode.Net生成二維碼(Qr碼)的方法

    C#利用QrCode.Net生成二維碼(Qr碼)的方法

    QrCode.Net是一個使用C#編寫的用于生成二維碼圖片的類庫,使用它可以非常方便的為WinForm、WebForm、WPF、Silverlight和Windows Phone 7應用程序提供二維碼編碼輸出功能。可以將二維碼文件導出為eps格式
    2016-12-12
  • C#如何自動選擇出系統(tǒng)中最合適的IP地址

    C#如何自動選擇出系統(tǒng)中最合適的IP地址

    這篇文章介紹了C#如何自動選擇出系統(tǒng)中最合適的IP地址,非常具有實用價值,需要的朋友可以參考下
    2015-08-08
  • C#開發(fā)微信公眾號接口開發(fā)

    C#開發(fā)微信公眾號接口開發(fā)

    這篇文章主要介紹了C#微信公眾號接口開發(fā),靈活利用網(wǎng)頁授權(quán)、帶參數(shù)二維碼、模板消息,提升用戶體驗之完成用戶綁定個人微信及驗證碼獲取,需要的朋友可以參考下
    2015-07-07
  • 一文探索C#中實現(xiàn)雙向鏈表的方法

    一文探索C#中實現(xiàn)雙向鏈表的方法

    這篇文章主要為大家詳細介紹了C#中的雙向鏈表的實現(xiàn),揭秘雙向鏈表內(nèi)實現(xiàn)諸多方法的那些事,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-03-03

最新評論

荥阳市| 吉林省| 溆浦县| 阿城市| 丘北县| 白沙| 抚宁县| 阿合奇县| 乐都县| 青浦区| 红安县| 三明市| 乌拉特前旗| 昭觉县| 淳化县| 沈阳市| 塘沽区| 伊川县| 宣汉县| 阳东县| 青阳县| 温州市| 金乡县| 达尔| 包头市| 上林县| 绿春县| 虎林市| 廊坊市| 皋兰县| 定襄县| 浦北县| 兴化市| 奉节县| 乌兰县| 行唐县| 安国市| 获嘉县| 中超| 图片| 怀集县|