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

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

 更新時間:2013年05月15日 16:00:27   作者:  
本篇文章是對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沒有關系呢?
當然不是,否則我寫這么一篇文章豈不是太蛋疼了……
字符串池和Intern方法簡直是實現(xiàn)Flyweight的神器?。?BR>考慮我們有某一類對象,可能會創(chuàng)建幾百萬個,對象里面恰巧有這么一個屬性叫做顏色,它在對象構造的時候隨機產(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)對象時使用類似的方式。

相關文章

  • C#中Byte轉(zhuǎn)換相關的函數(shù)

    C#中Byte轉(zhuǎn)換相關的函數(shù)

    這篇文章主要介紹了C#中Byte轉(zhuǎn)換相關的函數(shù)介紹,非常具有參考借鑒價值,特此分享到腳本之家平臺供大家學習
    2016-05-05
  • Unity實現(xiàn)老虎機滾動抽獎效果的示例代碼

    Unity實現(xiàn)老虎機滾動抽獎效果的示例代碼

    這篇文章主要介紹了Unity實現(xiàn)老虎機滾動抽獎效果的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-04-04
  • C#圖形區(qū)域剪切的實現(xiàn)方法

    C#圖形區(qū)域剪切的實現(xiàn)方法

    這篇文章主要介紹了C#圖形區(qū)域剪切的實現(xiàn)方法,涉及C#圖形操作的相關技巧,需要的朋友可以參考下
    2015-06-06
  • C#微信公眾號開發(fā)之接收事件推送與消息排重的方法

    C#微信公眾號開發(fā)之接收事件推送與消息排重的方法

    這篇文章主要介紹了C#微信公眾號開發(fā)之接收事件推送與消息排重的方法,詳細分析了事件推送與消息排重的使用技巧,對微信開發(fā)有一定參考借鑒價值,需要的朋友可以參考下
    2015-01-01
  • C# Struct的內(nèi)存布局問題解答

    C# Struct的內(nèi)存布局問題解答

    這篇文章介紹了C# Struct的內(nèi)存布局問題解答,有需要的朋友可以參考一下
    2013-11-11
  • Repeater控件綁定的三種方式

    Repeater控件綁定的三種方式

    Repeater 控件用于顯示重復的信息,這些信息被綁定在該控件上。一般項目中經(jīng)常出現(xiàn)三種使用方式
    2013-05-05
  • 詳解C#對XML、JSON等格式的解析

    詳解C#對XML、JSON等格式的解析

    這篇文章主要介紹了詳解C#對XML、JSON等格式的解析,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • C#面向?qū)ο笤O計原則之里氏替換原則

    C#面向?qū)ο笤O計原則之里氏替換原則

    這篇文章介紹了C#面向?qū)ο笤O計原則之里氏替換原則,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-03-03
  • C#策略模式(Strategy Pattern)實例教程

    C#策略模式(Strategy Pattern)實例教程

    這篇文章主要介紹了C#策略模式(Strategy Pattern),以一個簡單的實例講述了C#策略模式的實現(xiàn)方法,包括策略模式的用途以及具體實現(xiàn)方法,需要的朋友可以參考下
    2014-09-09
  • timespan使用方法詳解

    timespan使用方法詳解

    TimeSpan是用來表示一個時間段的實例,兩個時間的差可以構成一個TimeSpan實例,現(xiàn)在就來介紹一下使用方法
    2014-04-04

最新評論