【5min+】 設計模式的迷惑?Provider vs Factory

系列介紹

【五分鐘的dotnet】是一個利用您的碎片化時間來學習和豐富.net知識的博文系列。它所包含了.net體系中可能會涉及到的方方面面,好比C#的小細節,AspnetCore,微服務中的.net知識等等。
5min+不是超過5分鐘的意思,"+"是知識的增長。so,它是讓您花費5分鐘如下的時間來提高您的知識儲備量。html

正文

一提及設計模式,你們應該都不會太陌生。畢竟在面向對象的世界中,咱們須要用到各類奇技淫巧的手段來構建咱們的應用,而設計模式就是這些技巧的根本。若是您曾參與過計算機職業資格考試(俗稱軟考),就會發現:不管是初級、中級仍是高級,都會有關於設計模式的考題,並且分值比重還很大。這也側面說明了,學習設計模式的重要性。git

若是一談起設計模式,立馬浮如今您腦中的模式有哪些呢:「單例」、「迭代器」、「外觀」、「橋接」………… 然而,就在上週的時候,我忽然遇到了這麼一個問題:當我想爲建立一個對象進行抽象時,我不知道如何命名該建立類的名稱了。 您可能會說「這還不簡單,要建立確定是屬於建立類型,那很大概率就是「XXFactory」呀,就是所謂的工廠模式」。是的,我最初的時候也是這麼想的,可是我內心又出現了另外的一個單詞:「Provider」。程序員

Provider? 可能有些小夥伴會有一些陌生,由於它並無出如今GOF所提出的24個模式中。而它又是什麼東西呢? 通過我一番查找,發現它是由微軟在「.NET 1.1 framework」提出的一種模式。固然,距離.NET 1.1 framework發佈至今已通過了不少年了。也正是經歷了這麼多年的成長,因此微軟的許多代碼中您都會發現「Provider」的身影。 好比我們在AspNetCore中再熟悉不過的Logger,它就是由「ILoggerProvider」來建立的,還有依賴注入的「IServiceProvider」等等。github

疑惑

可能也是由於看多了「Provider」這個單詞,因此纔出現了我上面的糾結。可是,我忽然想了想,既然都是向外界提供一個結果,那麼Provider和Factory到底有什麼不一樣呢?算法

因而乎,我再次嘗試了 "百度不行就谷歌" 的程序員大法進行一波騷操做。可是看告終果以後個人心是拔涼拔涼啊:😭c#

x

好吧,這是在逼我下毒手啊!! 如是乎,我決定本身來好好分析它。設計模式

注:後文的內容都將以分析ILoggerProvider來做爲切入點。框架

固然,在進行了一圈瘋狂搜索以後,也不是沒有收穫的。在必應中我查詢到了這樣一篇文章:The .NET 2.0 Framework Provider Pattern,該文章中裏面提到了這樣的一段話:ide

x

它的意思是:Provider模式是 策略模式抽象工廠模式 的融合。微服務

因此在這以前咱們先來過一過 策略模式 於 抽象工廠模式吧,放心,時間不會太長。但願能在其中找到什麼奧祕:

策略模式

在策略模式(Strategy Pattern)中,一個類的行爲或其算法能夠在運行時更改。
這種類型的設計模式屬於行爲型模式(注意,這一點很重要)。

這裏我就直接引用runoob上面的圖片了,更多的模式說明您也能夠跳轉至對應連接

x

策略模式的幾個優勢:一、算法能夠自由切換。 二、避免使用多重條件判斷。 三、擴展性良好。

因此總結一下,策略模式其實提供了一個可拔插的替換方案。

抽象工廠

接下來,我們再來過一遍抽象工廠:抽象工廠模式(Abstract Factory Pattern)是圍繞一個超級工廠建立其餘工廠。該超級工廠又稱爲其餘工廠的工廠。這種類型的設計模式屬於建立型模式,它提供了一種建立對象的最佳方式。
這種類型的設計模式屬於建立型模式(注意,這一點很重要)。

x

可能這個圖看上去有一點點繞哈。說白了就是爲不一樣建立的結果都提供一個工廠。

因此它具備這樣的優勢:當一個產品族中的多個對象被設計成一塊兒工做時,它能保證客戶端始終只使用同一個產品族中的對象。

總結就是:它爲客戶端提供了一種開箱即用的功能,客戶端只管向工廠索取就能夠獲得結果了。

關於 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究竟是屬於 建立型模型仍是行爲型模式呢? 好吧,我也不知道。我的感受偏前一種更多一些吧。

本文內容僅供參考,由於該模式我並無查找到官方的解釋,大多數內容都是我的的理解。若有不足,還望各位大佬不吝賜教。😀

最後,偷偷說一句:點個推薦吧.....

x

相關文章
相關標籤/搜索