日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

身边的设计模式(三):抽象工厂 与 依赖注入

發(fā)布時(shí)間:2023/12/4 asp.net 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 身边的设计模式(三):抽象工厂 与 依赖注入 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上篇文章,我們說(shuō)到了簡(jiǎn)單工廠和工廠方法,如果沒看過(guò)的,請(qǐng)先看上篇,不然的話,可能有些吃力,或者直接點(diǎn)擊閱讀原文,查看我博客園的對(duì)應(yīng)詳細(xì)版的文章。

大家學(xué)到了這里,我建議自己可以練習(xí)練習(xí),可以寫一下部分代碼,很好的區(qū)分下【簡(jiǎn)單工廠】和【工廠方法】之間的區(qū)別和練習(xí),如果說(shuō)你已經(jīng)看懂了,或者說(shuō)自己已經(jīng)練習(xí)好了,那咱們就繼續(xù)往下說(shuō)今天的重要內(nèi)容?—— 抽象工廠。

?

再說(shuō)抽象工廠之前呢,咱們先簡(jiǎn)單總結(jié)一下:

1、我們知道,工廠模式屬于創(chuàng)建型開發(fā)模式的一元,他的作用就是創(chuàng)建我們需要的對(duì)象,如果一個(gè)一個(gè)創(chuàng)建的話,會(huì)很麻煩,所以我們誕生出來(lái)了一個(gè)【簡(jiǎn)單工廠】,這個(gè)簡(jiǎn)單工廠只是簡(jiǎn)單的人為的把幾個(gè)對(duì)象的實(shí)例給堆起來(lái),通過(guò)type 來(lái)區(qū)分,然后分別 new 實(shí)例化,有時(shí)候也是一個(gè)很好的方案,但是這樣有一個(gè)弊端,違背了我們開發(fā)六大原則中的——OCP開放關(guān)閉原則,所以這個(gè)時(shí)候,我們就又多出來(lái)一個(gè)新的概念【工廠方法】。

2、【工廠方法】是在【簡(jiǎn)單工廠】的基礎(chǔ)上,做了相應(yīng)的改良——通過(guò)多個(gè)子類的形式,來(lái)替換之前的 type 分類法,對(duì)內(nèi)修改關(guān)閉,對(duì)外新增打開,這樣無(wú)論是代碼整潔上,還是擴(kuò)展封裝上,都有了很好的體驗(yàn),同時(shí)也滿足了我們的OCP開發(fā)原則。

3、但是!這種方案真的就很好了么,我們?cè)賮?lái)回憶一下,我們無(wú)論是簡(jiǎn)單工廠,還是工廠方法,都是生成的單獨(dú)的一個(gè)類,好處是可以一一的慢慢擴(kuò)展,但歸根結(jié)底還是在處理一個(gè)類,我們平時(shí)開發(fā)的時(shí)候,處理一個(gè)類是很多,比如常見的helper,Log 之類的。但是這不是我們開發(fā)的重點(diǎn),我們平時(shí)使用最多的還是 Service 類,或者 Repository 類,里邊有很多,各種各樣的的類,比如 User 表,Role 表,Permission 表等等,每一個(gè)實(shí)體又都對(duì)應(yīng)各自的一個(gè)服務(wù)類或者倉(cāng)儲(chǔ)類。

4、那這個(gè)時(shí)候,我們使用上邊的【工廠方法】還行么?肯定是不行的!因?yàn)槲覀兩线吺且粋€(gè)二維體系,EFCoreRepository 、SugarRepository、DapperRepository等等,是這樣的二維,我們現(xiàn)在要做的就是在這個(gè)二維的基礎(chǔ)上,再加上一個(gè)維度,就是要解決 User 、Role、Permission 實(shí)體等等這種一組或者一系列的類創(chuàng)建的問(wèn)題。

5、那就是今天下邊要說(shuō)到的【抽象工廠】模式。

?

注意,下邊的例子可能不太恰當(dāng),只是作為理解抽象工廠模式來(lái)使用,具體開發(fā)中,可能有出入。

這篇文章內(nèi)容不是很全,我在博客園重新編排了一下,然后也同時(shí)加上了一個(gè)小故事,更方便理解,大家可以點(diǎn)擊【閱讀原文】來(lái)查看。

?

?一、抽象工廠模式

?

上邊的問(wèn)題我們都看到了,我們要解決一系列一組類創(chuàng)建的問(wèn)題,引申出來(lái)了抽象工廠模式,那下邊我們就簡(jiǎn)單寫一些代碼,看看是否跑的通。

1、創(chuàng)建一個(gè)核心層,添加多個(gè)倉(cāng)儲(chǔ)操作

我們畢竟要操作數(shù)據(jù)庫(kù)嘛,所以肯定需要倉(cāng)儲(chǔ)來(lái)持久化,那我們就創(chuàng)建一個(gè) FactoryPattern.Core 層,用來(lái)存放我們整個(gè)項(xiàng)目核心的底層。首先要?jiǎng)?chuàng)建的就是幾個(gè)倉(cāng)儲(chǔ):

/// <summary>/// 定義抽象的基類倉(cāng)儲(chǔ)/// </summary>public abstract class BaseRepository{ /// <summary> /// 創(chuàng)建 /// </summary> public abstract void Add(); /// <summary> /// 刪除 /// </summary> public abstract void Delete(); /// <summary> /// 修改 /// </summary> public abstract void Update(); /// <summary> /// 查詢 /// </summary>/ public abstract void Query();}


/// <summary> /// 定義抽象用戶倉(cāng)儲(chǔ),繼承抽象基類倉(cāng)儲(chǔ) /// 抽象的目的,是為了給UserRepositoryEFCore、UserRepositorySugar、 /// 做父類 /// </summary> public abstract class UserRepository: BaseRepository { }

/// <summary> /// 同 UserRepository /// </summary> public abstract class RoleRepository: BaseRepository { }
/// <summary> /// 同 UserRepository /// </summary> public abstract class PermissionRepository: BaseRepository { }?

?

那基本的倉(cāng)儲(chǔ)都已經(jīng)定義好了,現(xiàn)在就需要一個(gè)工廠來(lái)生產(chǎn)這一系列產(chǎn)品了,所以我們定義一個(gè)抽象工廠類:

/// <summary> /// 抽象工廠類,提供創(chuàng)建不同倉(cāng)儲(chǔ)接口 /// </summary> public abstract class AbstractFactory { // 抽象工廠提供創(chuàng)建一系列產(chǎn)品的接口 public abstract UserRepository UserRepository(); public abstract RoleRepository RoleRepository(); public abstract PermissionRepository PermissionRepository(); }

?

結(jié)構(gòu)如下:

?

2、創(chuàng)建EFCore倉(cāng)儲(chǔ)工廠層

說(shuō)人話就是,剛剛我們不是定義了一個(gè)抽象的工廠么,用來(lái)生產(chǎn)我們數(shù)據(jù)庫(kù)中一系列一組的產(chǎn)品,也就是數(shù)據(jù)庫(kù)表,那現(xiàn)在我們就需要指定具體的工廠來(lái)生產(chǎn)他們了,首先第一個(gè)我們就用EFCore這個(gè)工廠來(lái)生產(chǎn),創(chuàng)建一個(gè) FactoryPattern.Repository.EFCore 類庫(kù),并引用 Core 核心層

?

?

?

首先呢,我們就要在這一層中,對(duì)那幾個(gè)抽象的倉(cāng)儲(chǔ)類做重寫,對(duì)應(yīng)每一個(gè)EFCore 版本的倉(cāng)儲(chǔ)類,可能你會(huì)問(wèn)為什么,要每一個(gè)重寫下,還是OCP原則,而且還有一個(gè)愿意,Sqlsugar 可能某些表達(dá)式查詢,在EFCore里不能用,所以必須每一個(gè)重寫出來(lái)。

這里有一個(gè)地方就是,可以在EFCore也針對(duì)基類倉(cāng)儲(chǔ)做一個(gè)基類的,但是后來(lái)有類型不一致問(wèn)題,大家可以自己看看.

/// <summary> /// EFCore User 倉(cāng)儲(chǔ),繼承User倉(cāng)儲(chǔ) /// </summary> public class UserRepositoryEFCore : UserRepository { public override void Add() { throw new NotImplementedException(); }
public override void Delete() { throw new NotImplementedException(); }
public override void Query() { throw new NotImplementedException(); }
public override void Update() { throw new NotImplementedException(); } }

// 其他兩個(gè)表也是這個(gè)情況,不粘貼代碼了。

?

那現(xiàn)在有了子倉(cāng)儲(chǔ)產(chǎn)品了,我們就開始加工生產(chǎn)了,創(chuàng)建 EFCoreRepositoryFactory.cs ,并繼承抽象工廠,同時(shí)實(shí)現(xiàn)抽象方法:

/// <summary> /// EFCore 倉(cāng)儲(chǔ)子工廠 /// 用來(lái)生產(chǎn)各個(gè)實(shí)體倉(cāng)儲(chǔ) /// </summary> public class EFCoreRepositoryFactory : AbstractFactory { public override PermissionRepository PermissionRepository() { return new PermissionRepositoryEFCore(); }
public override RoleRepository RoleRepository() { return new RoleRepositoryEFCore(); }
public override UserRepository UserRepository() { return new UserRepositoryEFCore(); } }

?

?

結(jié)構(gòu)如下:

?

3、同理,創(chuàng)建Sugar倉(cāng)儲(chǔ)工廠層

過(guò)程和上邊的一模一樣,我就不多說(shuō)了,整體結(jié)構(gòu)還是這樣的:

?

?

?

?

4、控制器調(diào)用實(shí)例

我們?cè)?api 層,引用剛剛創(chuàng)建的兩個(gè)倉(cāng)儲(chǔ)層項(xiàng)目:

?

?

然后開始調(diào)用:

[HttpGet]public void Get(){ // 實(shí)例化工廠,這里用來(lái)生產(chǎn) efcore 這一系列的 產(chǎn)品 AbstractFactory efcoreFactory = new EFCoreRepositoryFactory(); efcoreFactory.UserRepository().Add(); efcoreFactory.RoleRepository().Delete(); efcoreFactory.PermissionRepository().Query();

// 實(shí)例化工廠,這里用來(lái)生產(chǎn) sugar 這一系列的 產(chǎn)品 AbstractFactory sugarFactory = new SugarRepositoryFactory(); sugarFactory.UserRepository().Add(); sugarFactory.RoleRepository().Delete(); sugarFactory.PermissionRepository().Query();}

?

結(jié)果我就不調(diào)試,肯定是沒有問(wèn)題的,畢竟僅僅是類的調(diào)用嘛,如果說(shuō)你從上邊往下看,看到了這里,還沒有問(wèn)題,并且能大概明白其中的意義,那你的工廠模式已經(jīng)完全學(xué)會(huì)了,特別是這個(gè)抽象工廠,一直很繞,而且也使用的不是很直觀,用途不是很多。

?

現(xiàn)在我們?cè)俸?jiǎn)單的說(shuō)明一下,我們通過(guò)【抽象工廠】模式,慢慢的明白了,其實(shí)抽象工廠是在【工廠方法】模式的基礎(chǔ)上,往外又多做了一套封裝,目的就是解決生產(chǎn)一系列產(chǎn)品的時(shí)候,工廠方法無(wú)法滿足的問(wèn)題。

所以這個(gè)時(shí)候,如果有人問(wèn)你二者的區(qū)別,核心的區(qū)別就是:如果是一個(gè)產(chǎn)品用工廠方法,一系列產(chǎn)品,用抽象工廠

?

但是雖然解決了問(wèn)題,還是有很多的問(wèn)題的,單單從上邊我們創(chuàng)建了那么多的子類,以及子類必須重寫這一點(diǎn)來(lái)看,這么設(shè)計(jì)肯定有弊端,那有什么改進(jìn)的呢?咱們繼續(xù)往下看

?

?

?二、抽象工廠與依賴注入

這里我就不詳細(xì)說(shuō)了,其實(shí)就是一個(gè)思路的用法,這里舉個(gè)例子就行了,大家肯定都用過(guò)三層架構(gòu),其中有一個(gè)數(shù)據(jù)訪問(wèn)層 DALFactory ,我們平時(shí)使用的時(shí)候,就是直接把類的實(shí)例給 return 出來(lái),如果我們同時(shí)連接多個(gè)數(shù)據(jù)庫(kù)呢?那這樣的話,我們就像上邊說(shuō)到的,建立多個(gè) DAL 層,比如 DALSqlServer、DALMysql 等等,那我們?nèi)绾瓮ㄟ^(guò)接口來(lái)獲取服務(wù)呢,就是通過(guò)反射指定的程序集來(lái)實(shí)現(xiàn),這個(gè)就是簡(jiǎn)單的使用了抽象工廠。

比如這個(gè)網(wǎng)上的圖片,就是這個(gè)意思,大家看個(gè)意思就行:

?

?

說(shuō)到這里大家有沒有了解到一些小小的心得,似乎這個(gè)和有一個(gè)東西很像!對(duì)!就是我們平時(shí)使用的依賴注入。其實(shí)我們可以想一想,我們?cè)诜?wù)注冊(cè)的時(shí)候,通過(guò)反射將多個(gè)服務(wù)注冊(cè)到容器里,然后我們?cè)偈褂玫臅r(shí)候,是容器通過(guò)接口別名,給我們找到指定的具體服務(wù),甚至也實(shí)現(xiàn)了一個(gè)接口,多個(gè)服務(wù)的操作,這個(gè)就是工廠模式和依賴注入的小小的關(guān)系。

?

總結(jié)一下:

今天我們通過(guò)簡(jiǎn)單的代碼,一步一步,從【簡(jiǎn)單工廠】開始,了解到了多個(gè)類是如何創(chuàng)建的,然后明白了【工廠方法】模式,更好的實(shí)現(xiàn)了OCP原則,也實(shí)現(xiàn)了封裝多態(tài)的原理,接下來(lái)咱們通過(guò)【抽象工廠】的舉例,進(jìn)一步對(duì)一系列一組產(chǎn)品生產(chǎn)的時(shí)候,所采用的方案,到最后,我們簡(jiǎn)單的說(shuō)明了一下反射以及依賴注入和工廠模式的關(guān)系,可能讀起來(lái)還是有點(diǎn)兒凌亂,不過(guò)我還是簡(jiǎn)單大家多多的學(xué)學(xué),查查資料,因?yàn)槲艺J(rèn)為,設(shè)計(jì)模式是結(jié)構(gòu)的基礎(chǔ),而工廠模式又是設(shè)計(jì)模式的基礎(chǔ),可見其重要性,如果看不懂沒關(guān)系,等我直播講課吧。?

當(dāng)然抽象工廠也是有一些弊端的,比如:

? ??3.1】、抽象工廠模式的優(yōu)點(diǎn):【抽象工廠】模式將系列產(chǎn)品的創(chuàng)建工作延遲到具體工廠的子類中,我們聲明工廠類變量的時(shí)候是使用的抽象類型,同理,我們使用產(chǎn)品類型也是抽象類型,這樣做就盡可能的可以減少客戶端代碼與具體產(chǎn)品類之間的依賴,從而降低了系統(tǒng)的耦合度。耦合度降低了,對(duì)于后期的維護(hù)和擴(kuò)展就更有利,這也就是【抽象工廠】模式的優(yōu)點(diǎn)所在。可能有人會(huì)說(shuō)在Main方法里面(這里的代碼就是客戶端的使用方)還是會(huì)使用具體的工廠類,對(duì)的。這個(gè)其實(shí)我們通過(guò)Net的配置,把這部分移出去,最后把依賴關(guān)系放到配置文件中。如果有新的需求我們只需要修改配置文件,根本就不需要修改代碼了,讓客戶代碼更穩(wěn)定。依賴關(guān)系肯定會(huì)存在,我們要做的就是降低依賴,想完全去除很難,也不現(xiàn)實(shí)。

???3.2】、抽象工廠模式的缺點(diǎn):有優(yōu)點(diǎn)肯定就有缺點(diǎn),因?yàn)槊糠N模式都有他的使用范圍,或者說(shuō)要解決的問(wèn)題,不能解決的問(wèn)題就是缺點(diǎn)了,其實(shí)也不能叫缺點(diǎn)了。【抽象工廠】模式很難支持增加新產(chǎn)品的變化,這是因?yàn)槌橄蠊S接口中已經(jīng)確定了可以被創(chuàng)建的產(chǎn)品集合,如果需要添加新產(chǎn)品,此時(shí)就必須去修改抽象工廠的接口,這樣就涉及到抽象工廠類的以及所有子類的改變,這樣也就違背了“開發(fā)——封閉”原則。

???3.3】、抽象工廠模式的使用場(chǎng)景:???如果系統(tǒng)需要多套的代碼解決方案,并且每套的代碼方案中又有很多相互關(guān)聯(lián)的產(chǎn)品類型,并且在系統(tǒng)中我們可以相互替換的使用一套產(chǎn)品的時(shí)候可以使用該模式,客戶端不需要依賴具體實(shí)現(xiàn)。

?

?

?三、示例代碼

https://github.com/anjoy8/DesignPattern/tree/master/FactoryPattern

?

【參考文獻(xiàn):】

1、Dependency Injection vs Factory Pattern

總結(jié)

以上是生活随笔為你收集整理的身边的设计模式(三):抽象工厂 与 依赖注入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。