系列介紹
【五分鍾的dotnet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,比如C#的小細節,AspnetCore,微服務中的.net知識等等。
5min+不是超過5分鍾的意思,"+"是知識的增加。so,它是讓您花費5分鍾以下的時間來提升您的知識儲備量。
正文
一說起設計模式,大家應該都不會太陌生。畢竟在面向對象的世界中,我們需要用到各種奇技淫巧的手段來構建我們的應用,而設計模式就是這些技巧的根本。如果您曾參與過計算機職業資格考試(俗稱軟考),就會發現:無論是初級、中級還是高級,都會有關於設計模式的考題,而且分值比重還很大。這也側面說明了,學習設計模式的重要性。
如果一談起設計模式,立馬浮現在您腦中的模式有哪些呢:“單例”、“迭代器”、“外觀”、“橋接”………… 然而,就在上周的時候,我突然遇到了這么一個問題:當我想為創建一個對象進行抽象時,我不知道如何命名該創建類的名稱了。 您可能會說“這還不簡單,要創建肯定是屬於創建類型,那很大幾率就是“XXFactory”呀,就是所謂的工廠模式”。是的,我最初的時候也是這么想的,但是我心里又出現了另外的一個單詞:“Provider”。
Provider? 可能有些小伙伴會有一些陌生,因為它並沒有出現在GOF所提出的24個模式中。而它又是什么東西呢? 經過我一番查找,發現它是由微軟在“.NET 1.1 framework”提出的一種模式。當然,距離.NET 1.1 framework發布至今已經過了很多年了。也正是經歷了這么多年的成長,所以微軟的許多代碼中您都會發現“Provider”的身影。 比如咱們在AspNetCore中再熟悉不過的Logger,它就是由“ILoggerProvider”來創建的,還有依賴注入的“IServiceProvider”等等。
疑惑
可能也是因為看多了“Provider”這個單詞,所以才出現了我上面的糾結。但是,我突然想了想,既然都是向外界提供一個結果,那么Provider和Factory到底有什么不同呢?
於是乎,我再次嘗試了 "百度不行就谷歌" 的程序員大法進行一波騷操作。但是看了結果之后我的心是拔涼拔涼啊:😭
好吧,這是在逼我下毒手啊!! 如是乎,我決定自己來好好分析它。
注:后文的內容都將以分析ILoggerProvider來作為切入點。
當然,在進行了一圈瘋狂搜索之后,也不是沒有收獲的。在必應中我查詢到了這樣一篇文章:The .NET 2.0 Framework Provider Pattern,該文章中里面提到了這樣的一段話:
它的意思是:Provider模式是 策略模式 於 抽象工廠模式 的融合。
所以在這之前我們先來過一過 策略模式 於 抽象工廠模式吧,放心,時間不會太長。希望能在其中找到什么奧秘:
策略模式
在策略模式(Strategy Pattern)中,一個類的行為或其算法可以在運行時更改。
這種類型的設計模式屬於行為型模式(注意,這一點很重要)。
這里我就直接引用runoob上面的圖片了,更多的模式說明您也可以跳轉至對應鏈接。
策略模式的幾個優點:1、算法可以自由切換。 2、避免使用多重條件判斷。 3、擴展性良好。
所以總結一下,策略模式其實提供了一個可拔插的替換方案。
抽象工廠
接下來,咱們再來過一遍抽象工廠:抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠創建其他工廠。該超級工廠又稱為其他工廠的工廠。這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
這種類型的設計模式屬於創建型模式(注意,這一點很重要)。
可能這個圖看上去有一點點繞哈。說白了就是為不同創建的結果都提供一個工廠。
所以它具有這樣的優點:當一個產品族中的多個對象被設計成一起工作時,它能保證客戶端始終只使用同一個產品族中的對象。
總結就是:它為客戶端提供了一種開箱即用的功能,客戶端只管向工廠索取就可以得到結果了。
關於 Provider
好了,回到主題,那么關於Provider呢? 它到底是什么樣子呢?這里來看一看 .NET Core Logger的相關接口:
public interface ILoggerProvider : IDisposable
{
ILogger CreateLogger(string categoryName);
}
public interface ILoggerFactory : IDisposable
{
ILogger CreateLogger(string categoryName);
void AddProvider(ILoggerProvider provider);
}
是的,不管是Provider 和 Factory 都具有一個叫做“CreateLogger”的方法。也就是說,他們都具有創建Logger的能力。 那么我到底應該什么時候才使用Provider,什么時候才使用Factory呢? 這也是我最初十分糾結的原因。
但是從ILoggerFactory的另外一個方法,也許能看出端倪:AddProvider。 這就證明了,可以往工廠里面添加Provider。也就是說工廠里面可能存在着許許多多的提供程序。而這些提供程序可能都將是最后工廠創建出結果的必要支撐。
還記得上面咱們說的那兩個模式的特點嗎? 策略模式是為了可拔插可替換方案,而factory是為了屏蔽細節的創建。假如Provider是結合了這兩者的話,也就是說它可能會具有這兩者的全部優點:可拔插+創建。
也就是說我們可以在項目中根據已有的provider接口,演變出各種的策略來,比如 XMLLogProvider、ConsoleLogProvider、JsonLogProvider等等。
但是它僅僅關注的是它要創建的細粒度對象,而不像工廠一樣負責各個粒度對象的拼裝,最終產生一個大粒度對象。
那么我們能將各種Provider再提供給工廠,然后再讓它來負責最終大對象的創建嗎?。 是的,ILoggerFactory就是干了這樣的事情。有興趣的同學可以查看它的實現代碼。
一個小故事
有一個名人叫做Bob,他平時被各種商業會談所占據了大部分的時間。所以他很聰明,將一些繁瑣的事情都交給了他的管家。
這不,明天Bob就要參加一個晚會,但是高端的晚會是需要配上高端的禮服的。Bob肯定沒有心思去打理這些事情,所以他就把這個事情交給了他的管家。
管家收到了命令之后,立即做出了反應。他知道他得在今天為Bob采購一套完美的禮服,包括禮帽,燕尾服等。 但是管家一想,我又不會做衣服啊。所以他電話聯系了周圍所有的服裝廠商來和他們洽談。哪個廠商提供怎樣的衣服他都安排了下去,到最后各個廠商把衣服做好了之后都給了管家,並得到了自己應有的報酬。
最后,管家在采購的眾多衣服中為Bob搭配了一個最好看的禮服。
在上面這個故事中,您可以把Bob理解為咱們的客戶端,管家理解為工廠,服裝供應商理解為Provider。 客戶端只需要讓工廠創建需要的東西就行了,它並不想知道這個東西是怎么來的。就好比Bob哪兒有那么多時間來關心衣服怎么來的一樣。 而工廠去找提供程序獲取所需要的東西。就好比管家去找服裝廠商。
這么一看,Provider確實是在干它自己分內的事情,它只負責小顆粒對象的創建。就好比服裝廠商,我只造帽子就只造帽子。而且它是可以隨時替換的,就相當於上文管家可以聯系其它的廠商一樣,只要附近有廠商就可以了。
總結
那么用了這樣的模式好處到底在哪兒呢? 就像上面的故事來說,Bob需要禮服的時候他只需要安排管家就可以了,管家離職了可以再換一個。而管家做禮服的時候,可以有許許多多的方案來備選,只要周圍有服裝廠商就可以了,方案不好就換一個廠商就行了。所以對於客戶端來說,代碼一直都沒有變過(只需要叫工廠拿),而工廠又去找提供商。
所以,您會發現,咱們的代碼同樣是用的Logger,但是用了不同的日志框架(比如serilog)之后,日志顯示的結果和存放的方式就可能不一樣了。 因為日志框架的底部實現了對應的日志提供代碼。
總結一下Provider: 當我們需要創建一個小粒度對象的時候並且該對象未來可能會有多種創建方案的時候可以考慮使用Provider。
那么Provider到底是屬於 創建型模型還是行為型模式呢? 好吧,我也不知道。個人感覺偏前一種更多一些吧。
本文內容僅供參考,因為該模式我並沒有查找到官方的解釋,大多數內容都是個人的理解。如有不足,還望各位大佬不吝賜教。😀
最后,偷偷說一句:點個推薦吧.....