您好,登錄后才能下訂單哦!
如何分析.NET獨有精巧泛型設計模式,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
雖然泛型出現已有多年,連Java都早已借鑒引入了泛型(雖然是語法糖),可是用泛型的編程思維方式并沒有得到相應的普及。一方面是由于過去大量的Framework仍然是在非泛型時代寫成的,另一方面泛型的設計模式沒有得到發展,改變的時候該到了。
來舉一個例子說明這兩點。我們如果寫過網絡數據抓取的代碼,應該熟悉這樣的代碼:
var request = WebRequest.Create("http://www.cnblogs.com/") as HttpWebRequest;
或者這么寫,也是一樣:
var request = HttpWebRequest.Create("http://www.cnblogs.com/") as HttpWebRequest;
大家可想過,為什么每次都要as一下?
類似的情況還有,比如做圖像處理的弟兄會熟悉:
var bm = Image.FromFile("e:\\me.jpg") as Bitmap;
和
var bm = Bitmap.FromFile("e:\\me.jpg") as Bitmap;
我想過,但沒想明白。上面兩種寫法,都是調用父類的工廠方法,實際返回了一個子類的實例。顯然,即使不了解OCP,憑直覺也應該想到,父類的實現中不應該被子類所決定。寫WebRequest和Image的前輩可能也覺得直接返回子類實例不妥,所以陰險地把方法簽名的返回類型改成了父類。
雖然這種行徑值得嚴重鄙視。但.NET程序員大都是人云亦云,照葫蘆畫瓢的好學生,所以這個問題多年了也沒有修改。
理想的設計應該是這樣:父類的每個子類,都有獨立的工廠方法,返回其自身的實例。這樣做法,在泛型出現前非常笨拙,得不償失,但有了泛型,就可以精巧地實現。
以模擬Image類為例,Image和BitMap實現如下:
class Image<T> where T:Image<T>, new() { public string Path { get; set; } public static T FromFile(string path) { return new T() { Path = path }; } } class Bitmap:Image<Bitmap> { }
Image自身的工廠方法,就沒有存在的必要了。
可以簡單地測試一下:
var path = @"e:\me.jpg"; var bm = Bitmap.FromFile(path); ; Console.WriteLine(bm.Path); Console.WriteLine(bm.GetType().Name);
輸出結果如下:
Path: e:\me.jpg Type: Bitmap
為了讓大家更熟悉一下,再舉一個實現數據結構中的二叉樹作例子。
傳統的樹節點類,無論無論C/C++/Java都是類似這樣:
class TreeNode { public TreeNode LeftChild { get; set; } public TreeNode RightChild { get; set; } public TreeNode Parent { get; set; } public int Value { get; set; } }
大家知道,二叉樹又分好幾種,AVL樹、B樹、紅黑樹等等。實現特殊的二叉樹數據結構,勢必要繼承TreeNode。由于樹節點的類型中,有類型為基類的成員,所以在子類操作這些成員時,往往也要強制轉換類型,這比Image和WebRequest的例子,只在實例創建時轉換類型還麻煩。
這就該泛型模式一顯身手的好機會了,請看其父類型的實現:
/// <typeparam name="T">Type of the node.</typeparam> /// <typeparam name="K">Type of the node value.</typeparam> class TreeNode<T,K> where T:TreeNode<T,K> where K: IComparable<K> { public T LeftChild { get; set; } public T RightChild { get; set; } public T Parent { get; set; } public K Value { get; set; } }
之后,實現任何一種特殊二叉樹結構,比如RBTreeNode代表紅黑樹節點,可以這樣:
class RBTreeNode : TreeNode<RBTreeNode,Int32> { /// <summary> /// 樹節點顏色,是否為紅。 /// </summary> public bool IsRed { get; set; } public override string ToString() { return this.Value + "," + (this.IsRed ? "R" : "B"); } }
這個是AVL樹:
class AvlTreeNode : TreeNode<AvlTreeNode,Int32> { /// <summary> /// 節點的平衡度 /// </summary> public int Balance { get; set; } public override string ToString() { return "Balance: " + Balance + ", Value: " + this.Value; } }
不但完全符合OCP原則,而且再也不需要as來強制轉換節點類型了。
這肯定不是我的首創,其實.NET Framework中已經不少這樣的設計,比如IComparable<T>接口。也有不少優秀的框架采用了類似的設計,比如大石頭同學的ORM框架NewLife.XCode。
看上去也很簡單吧,但是很多人思維還停留在面向對象語言剛誕生的階段,還不習慣用這種設計模式。我認為這種寫法足夠典型和通用,足以得上一種設計模式,而且是.NET特殊優勢,獨特魅力。
說到設計模式,其實GOF提出的23種設計模式多年了,已經過時,出現了許多新模式(比如并發編程方面,參考Wiki Design Pattern)。舊有的模式中,有的已經包含在.NET語言特性中,有的模式實現方式已經改頭換面。尤其在泛型出現后,許多模式的實現可以變得簡潔許多,優雅許多。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。