前面我們學(xué)習(xí)了工廠模式和工廠方法模式桅锄,下面做一個(gè)簡(jiǎn)單的回顧:
簡(jiǎn)單工廠模式:是為了將具體類的實(shí)例化和這個(gè)類對(duì)象的應(yīng)用分離出來琉雳,
工廠方法模式:是為了讓簡(jiǎn)單工廠方法滿足”對(duì)擴(kuò)展開放样眠,對(duì)修改關(guān)閉”,將對(duì)象的創(chuàng)建推遲到子類中
下面我們要學(xué)習(xí)的就是工廠模式家族中最后一個(gè)設(shè)計(jì)模式抽象工廠模式翠肘。抽象工廠模式提供了一個(gè)創(chuàng)建一系列相關(guān)對(duì)象或者一系列相互依賴對(duì)象的接口檐束。抽象工廠定義了一系列的用來生產(chǎn)不同等級(jí)結(jié)構(gòu)下的同一產(chǎn)品族接口,不需要關(guān)心具體產(chǎn)品是什么束倍,這樣一來將客戶從具體的產(chǎn)品中解耦出來被丧。
1:什么是抽象工廠模式
定義:提供了一個(gè)接口,用于創(chuàng)建相關(guān)的或相互依賴的一組對(duì)象家族
類圖:
抽象工廠接口(IFactory):定義了一組方法绪妹,每個(gè)方法都用來創(chuàng)建一個(gè)具體產(chǎn)品
具體工廠(Factory):實(shí)現(xiàn)了產(chǎn)品接口, 完成具體產(chǎn)品的創(chuàng)建
產(chǎn)品A/B抽象類(Abstract Product A/B):是一個(gè)抽象類,用于具體工廠來生產(chǎn)產(chǎn)品
具體產(chǎn)品A/B類(Concrete Product A/B):具體工廠生產(chǎn)出來的產(chǎn)品
業(yè)務(wù)場(chǎng)景:
? ? 繼續(xù)我門的月餅加盟店案例甥桂,隨著我們的品牌越來越好,每個(gè)城市都出現(xiàn)了很多的線下店鋪邮旷,但同時(shí)也出現(xiàn)了一個(gè)新的問題那就是店鋪使用的原料(面粉黄选,油等)的不正規(guī)現(xiàn)象。所以為了保證我們的品質(zhì)婶肩,保證每家店鋪的原料都和安全合格有機(jī)的办陷,我不得不繼續(xù)升級(jí)我們的項(xiàng)目,來保證所有的原料都出至一家律歼,都由總部統(tǒng)一配送懂诗。
2:實(shí)現(xiàn)抽象工廠模式
分析場(chǎng)景:
? ? ? 在我們上面描述的場(chǎng)景中,每個(gè)月餅都需要面粉和油苗膝,但是不同區(qū)域使用的面粉和油不一樣。那我們的(高筋面粉植旧,中筋面粉辱揭,低筋面粉),(胡麻油病附,色拉油问窃,大豆油)就夠成了三個(gè)不同的產(chǎn)品族,同時(shí)面粉和油便認(rèn)為是我們的產(chǎn)品等級(jí)完沪。如下圖:
通過上面的分析域庇,我就可以確定我們的產(chǎn)品族和產(chǎn)品等級(jí)了,那我們的IFactory就只需要提供2個(gè)產(chǎn)品的生產(chǎn)接口覆积,我門的實(shí)體工廠ConcreteFactory需要3個(gè)來生產(chǎn)本地化的具體產(chǎn)品听皿,下面針對(duì)我們的場(chǎng)景來設(shè)計(jì)一份我們自己的類圖:
這樣一來,我們就完美的把這個(gè)場(chǎng)景映射到了抽象工廠模式中宽档,這樣一來尉姨,我們便解決了原料的安全隱患,接下來讓我們來思考一下吗冤,如何設(shè)計(jì)我們的月餅又厉,線下商鋪九府,讓他們完美協(xié)作。
首先我們需要一個(gè)線下的實(shí)體店方便我們點(diǎn)餐覆致,每個(gè)實(shí)體店都需要生產(chǎn)月餅也就意味著每個(gè)實(shí)體店都需要再維護(hù)一個(gè)原料工廠侄旬。依據(jù)我們的依賴倒置原則,抽象一個(gè)月餅類和一個(gè)月餅店的接口煌妈,類圖設(shè)計(jì)如下:
完成上面復(fù)雜的分析后剩下的工作就是用code來實(shí)現(xiàn)我們的類圖設(shè)計(jì)儡羔。
定義工廠接口,用來生產(chǎn)一組面粉和油
定義實(shí)體工廠SCFactory声旺,來生產(chǎn)低筋面粉和色拉油
定義實(shí)體工廠NMFactory笔链,來生產(chǎn)高筋面粉和胡麻油
定義實(shí)體工廠BJFactory,來生產(chǎn)中筋面粉和大豆油
定義我們面粉類產(chǎn)品
定義我們的油類產(chǎn)品
定義我們的月餅家族
定義我們的客戶端腮猖,實(shí)體加盟店鋪
好了鉴扫,可以下單了,走進(jìn)內(nèi)蒙地區(qū)加盟店澈缺,點(diǎn)個(gè)肉陷月餅
工程介紹:
IFactory:月餅的原料工廠接口坪创,定義生產(chǎn)一個(gè)月餅需要的相關(guān)產(chǎn)品的家族創(chuàng)建,
SCFactory,NMFactory,BJFactory:負(fù)責(zé)生產(chǎn)具體的原料姐赡,每個(gè)工廠都會(huì)生產(chǎn)符合自己的產(chǎn)品原料
Dough,HighDough,MiddleDough,LowDough:面粉的家族
Oil,FlaxOil,SoybeanOil,SaladOil:油的家族
MoonCakeSotre:線下加盟店鋪莱预,用來生產(chǎn)具體區(qū)域的月餅(如:內(nèi)蒙店鋪就只需要內(nèi)蒙的工廠來提供的面粉和油,符合當(dāng)?shù)氐目谖叮?/p>
3:抽象工廠的使用場(chǎng)景
切換數(shù)據(jù)庫(kù)或者添加新的數(shù)據(jù)庫(kù):
抽象工廠就會(huì)突顯的尤為重要项滑,例如:我們工程中有三個(gè)DAO:DAO1, DAO2, DAO3;但是在不用的數(shù)據(jù)庫(kù)(Sqlsever, my Sql, Access)中語法有些小的差異依沮,那當(dāng)我們要切換數(shù)據(jù)庫(kù)就需要把每個(gè)DAO里面的SQL都修改成相應(yīng)的語法,這樣的工程就違反了我們的“開閉原則“枪狂。讓我們使用抽象工程來解決這個(gè)問題:
1:我們創(chuàng)建一個(gè)IFacotry定義一組生成DAO層的接口
2:創(chuàng)建我門的各個(gè)產(chǎn)品類和對(duì)應(yīng)的接口(在代碼中要依賴抽象危喉,不依賴具體對(duì)象),IDAO1州疾,DAO1,? IDAO2辜限,DAO2, IDAO3, DAO3
3:創(chuàng)建三個(gè)SQL的具體工廠,(Sql Server Factroy, MySqlFactory, Access Factory)實(shí)現(xiàn)IFactory接口并返回具體的產(chǎn)品對(duì)象
如果我們需要添加/切換新的數(shù)據(jù)庫(kù)严蓖,就只需要添加新的DAO層實(shí)現(xiàn)和新的Factory并實(shí)現(xiàn)IFactory接口就ok,不需要修改任何代碼薄嫡。
4:抽象工廠的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
? ? 1):抽象工廠可以把一系列相關(guān)的產(chǎn)品集合起來,當(dāng)需要多個(gè)產(chǎn)品同時(shí)協(xié)作時(shí)可以保證所有的產(chǎn)品生產(chǎn)的一致性(比如我們的月餅需要的原料),并隔離具體產(chǎn)品的創(chuàng)建
? ? 2):當(dāng)有新產(chǎn)品族加入時(shí)颗胡,不許要修改代碼毫深,只需要添加一個(gè)具體的工廠
? ? 3):通過組合的方式創(chuàng)建對(duì)象,使用應(yīng)用程序解耦毒姨,同時(shí)降低對(duì)特定對(duì)象 的依賴
缺點(diǎn):
? ? 如果有產(chǎn)品等級(jí)加入费什,就需要修改工廠接口和所有的具體工廠