工廠模式屬于創(chuàng)建類(lèi)模式,一般情況下根據(jù)使用場(chǎng)景和實(shí)現(xiàn)方式分為4種:簡(jiǎn)單工廠模式(
Simple Factory Pattern
)厨剪、靜態(tài)工廠模式(Static Factory Pattern
)估灿、工廠方法模式(Factory Method Pattern
)棉磨、抽象工廠模式(Abstract Factory Pattern
)叁温。
在學(xué)習(xí)設(shè)計(jì)模式的時(shí)候建議不要去生搬硬套類(lèi)圖再悼,而是去學(xué)習(xí)這種模式的思想以及關(guān)注它是怎么去解決這一類(lèi)問(wèn)題的,所以后面的東西都是以這兩個(gè)目的去分享自己的心得膝但。
下面的例子不恰當(dāng)冲九,能夠明白工廠模式就行。朋友在成都開(kāi)了一個(gè)茶坊跟束,想做一個(gè)茶葉管理的系統(tǒng)≥杭椋現(xiàn)在簡(jiǎn)單的分析一下需求,給這個(gè)系統(tǒng)添加一個(gè)簡(jiǎn)單的下單功能冀宴,顧客來(lái)買(mǎi)茶的時(shí)候能夠通過(guò)客戶(hù)端下單灭贷。
先做一個(gè)簡(jiǎn)單的版本,通過(guò)TeaStore
根據(jù)不同類(lèi)型的茶下單:
fun main(args: Array<String>)
{
val redStore:TeaStore = TeaStore()
redStore.order(TeaStore.TeaType.RED).getTea()
redStore.order(TeaStore.TeaType.GREEN).getTea()
}
新建一個(gè)TeaStore
,然后顧客點(diǎn)了一杯紅茶,一杯綠茶。從下面的代碼可以看到蒿偎,現(xiàn)在系統(tǒng)只有紅茶和綠茶典蜕。
class TeaStore
{
enum class TeaType
{
RED,
GREEN,
BLACK,
YELLOW,
}
/**
* 下單
*/
fun order(type: TeaType): Tea
{
val tea = when (type)
{
TeaType.RED -> RedTea()
TeaType.GREEN -> GreenTea()
}
tea.addWater()
tea.cook()
return tea
}
}
現(xiàn)在有顧客希望能夠在店子里面喝到黃茶,所以系統(tǒng)得支持黃茶類(lèi)型,這個(gè)時(shí)候我們可以這樣修改TeaStroe
:
/**
* 下單
*/
fun order(type: TeaType): Tea
{
val tea = when (type)
{
TeaType.RED -> RedTea()
TeaType.GREEN -> GreenTea()
TeaType.YELLOW -> YellowTea() // 新增一種
}
tea.addWater()
tea.cook()
return tea
}
現(xiàn)在我們下單的時(shí)候就可以添加黃茶類(lèi)型了。現(xiàn)在的問(wèn)題是每添加一種茶都得在這里修改switch里面的條件,顯然不符合開(kāi)閉原則黄痪。
簡(jiǎn)單工廠模式
類(lèi)圖不是目的,僅僅幫助理解
[圖片上傳失敗...(image-e21af9-1527174175649)]
簡(jiǎn)單工廠可以解決每次去修改直接消費(fèi)類(lèi)的代碼盔然。接下來(lái)用簡(jiǎn)單工廠模式實(shí)現(xiàn)一個(gè)版本桅打,用工廠來(lái)生產(chǎn)Tea
類(lèi)的實(shí)例:
class SimpleFactory
{
/**
* 創(chuàng)建茶
*/
fun createTea(type: TeaStore.TeaType): Tea
{
return when (type)
{
TeaStore.TeaType.RED -> RedTea()
TeaStore.TeaType.GREEN -> GreenTea()
else -> NoneTea()
}
}
}
然后修改一下下單的代碼使用工廠創(chuàng)建類(lèi):
/**
* 下單
*/
fun order(type: TeaType): Tea
{
val tea = SimpleFactory.createTea(type)
tea.addWater()
tea.cook()
return tea
}
現(xiàn)在用簡(jiǎn)單工廠代替swith創(chuàng)建的Tea
類(lèi)。咦愈案,等等挺尾,現(xiàn)在我要添加一種茶的時(shí)候怎么辦?打開(kāi)工廠類(lèi)SimpleFactory
站绪,然后繼續(xù)添加swith分支遭铺。肯定會(huì)奇怪恢准,這不是跟之前一樣嘛魂挂,只是換了個(gè)地方修改,這里只有TeaStroe
在生產(chǎn)消費(fèi)Tea
這個(gè)類(lèi)的實(shí)例馁筐,假如有100個(gè)地方呢涂召?
設(shè)計(jì)模式在做的只有一件事情:封裝變化,把經(jīng)常在變化的代碼封裝到一個(gè)黑盒子里面敏沉,使整體看起來(lái)是不變的果正。
簡(jiǎn)單工廠模式解決的問(wèn)題就是封裝創(chuàng)建類(lèi)的變化炎码,把Tea
類(lèi)別的修改控制在工廠類(lèi)里面,任何使用工廠類(lèi)產(chǎn)生Tea
類(lèi)實(shí)例的地方不需要再去修改秋泳。
最后說(shuō)明一下簡(jiǎn)單工廠模式和靜態(tài)工廠模式的區(qū)別潦闲,如果你把
createTea()
實(shí)現(xiàn)成靜態(tài)方法就是靜態(tài)工廠模式,如果實(shí)現(xiàn)成類(lèi)方法就是簡(jiǎn)單工廠模式迫皱。
由于用了我們的系統(tǒng)歉闰,茶館效率提高了賺了很多錢(qián),現(xiàn)在在軟件園開(kāi)了一個(gè)分店舍杜,為了適應(yīng)不同人群每個(gè)店子賣(mài)不同的茶,軟件園賣(mài)茶添加了其它興奮劑赵辕,代碼紅茶(喝了寫(xiě)代碼沒(méi)bug)和代碼綠茶既绩,之前的店子在東邊直接叫東店好了,賣(mài)普通紅茶和普通綠茶还惠。之前的方式只能滿(mǎn)足對(duì)茶的修改饲握,對(duì)茶店的擴(kuò)展就滿(mǎn)足不到了。
工廠方法模式
工廠方法模式(英語(yǔ):Factory method pattern)蚕键,就像其他創(chuàng)建型模式一樣救欧,它也是處理在不指定對(duì)象具體類(lèi)型的情況下創(chuàng)建對(duì)象的問(wèn)題。工廠方法模式的實(shí)質(zhì)是“定義一個(gè)創(chuàng)建對(duì)象的接口锣光,但讓實(shí)現(xiàn)這個(gè)接口的類(lèi)來(lái)決定實(shí)例化哪個(gè)類(lèi)笆怠。工廠方法讓類(lèi)的實(shí)例化推遲到子類(lèi)中進(jìn)行√艿”
類(lèi)圖不是目的蹬刷,僅僅幫助理解
[圖片上傳失敗...(image-485df-1527174175650)]
從類(lèi)圖可以看到,我們把創(chuàng)建茶的方法放到了茶店频丘,有一個(gè)抽象的茶店TeaStore
办成,并且把創(chuàng)建Tea
實(shí)例的方法放到了TeaStroe
的子類(lèi)。
abstract class TeaStore
{
enum class TeaType
{
RED,
GREEN,
BLACK,
YELLOW,
}
/**
* 下單
*/
fun order(type: TeaType): Tea
{
val tea: Tea = createTea(type)
print("\n--------------------")
tea.addWater()
tea.cook()
return tea
}
// 創(chuàng)建類(lèi)的方法放到子類(lèi)去決定
abstract protected fun createTea(type: TeaType): Tea
}
基于抽象茶店實(shí)現(xiàn)兩個(gè)不同地方的茶店:
class SoftTeaStore : TeaStore()
{
override fun createTea(type: TeaType): Tea
{
return when (type)
{
TeaType.RED -> CodeRedTea()
TeaType.GREEN -> CodeGreenTea()
else -> NoneTea()
}
}
}
class EastTeaStore : TeaStore()
{
override fun createTea(type: TeaType): Tea
{
return when (type)
{
TeaType.RED -> RedTea()
TeaType.BLACK -> BlackTea()
TeaType.GREEN -> GreenTea()
else -> NoneTea()
}
}
}
可以看到軟件園的茶店買(mǎi)的紅茶是代碼紅茶搂漠,綠茶是代碼綠茶迂卢,東店賣(mài)的是普通的茶。現(xiàn)在用這兩個(gè)店分別點(diǎn)一杯茶:
fun main(args: Array<String>)
{
val redStore:TeaStore = EastTeaStore()
// 在軟件園點(diǎn)了一杯紅茶
redStore.order(TeaStore.TeaType.RED).getTea()
val greenStore: TeaStore = SoftTeaStore()
// 在東店點(diǎn)了一杯綠茶
greenStore.order(TeaStore.TeaType.GREEN).getTea()
}
在軟件園的紅茶桐汤,顧客拿到的添加了興奮劑的紅茶而克,在東店拿到的紅茶是普通的綠茶。現(xiàn)在如果添加一種茶不管是在軟件園還是東店跟之前一樣只需要修改工廠方法怔毛,和之前不同的是現(xiàn)在不但可以根據(jù)地域不同擴(kuò)展不同的茶還可以新增新的店子比如北店拍摇、黑店什么的,我們的客戶(hù)端Main就是消費(fèi)tea的地方不用修改馆截。
抽象工廠模式
抽象工廠模式(英語(yǔ):Abstract factory pattern)充活,抽象工廠模式提供了一種方式蜂莉,可以將一組具有同一主題的單獨(dú)的工廠封裝起來(lái)。
類(lèi)圖不是目的混卵,僅僅幫助理解
[圖片上傳失敗...(image-5a426f-1527174175650)]
現(xiàn)在假如我們需要給茶添加不同工藝映穗,比如軟件園的茶店就不能是普通的水 必須是礦泉水,溫度也不能是80-100幕随,只能是20度干泡蚁滋。所以現(xiàn)在泡茶用的水等等需要分區(qū)域單獨(dú)提供,這樣的話(huà)我們的工廠就需要生產(chǎn)一系列的材料赘淮,和工廠方法模式一樣辕录,只是多了一些創(chuàng)建水的工廠方法:
class SoftTeaStore : TeaStore()
{
// 創(chuàng)建茶
override fun createTea(type: TeaType): Tea
{
return when (type)
{
TeaType.RED -> CodeRedTea()
TeaType.GREEN -> CodeGreenTea()
else -> NoneTea()
}
}
// 創(chuàng)建泡茶的水
override fun createWater(type: WaterType) : Water
{
return when (type)
{
WaterType.WHITE -> WhiteWater()
WaterType.NORMAL -> NormalWater()
else -> NoneWater()
}
}
}
這樣的話(huà)就把一系列工藝限制在了一個(gè)工廠里面,就不會(huì)出現(xiàn)東店使用礦泉水的情況梢卸,還能規(guī)范流程和生產(chǎn)方試走诞。同樣的新增一種茶或者茶店,很方便的根據(jù)需求定制不同的茶店蛤高。
總結(jié)
總結(jié)一下蚣旱,因?yàn)橛袝r(shí)候類(lèi)的創(chuàng)建和初始化是比較重的,如果在每個(gè)使用的地方去實(shí)例化就會(huì)造成很多重復(fù)代碼戴陡,工廠模式可以統(tǒng)一創(chuàng)建類(lèi)以及初始化塞绿。工廠模式分為4種:簡(jiǎn)單工廠模式、靜態(tài)工廠模式恤批、工廠方法模式异吻、抽象工廠模式。其中簡(jiǎn)單工廠模式喜庞、靜態(tài)工廠模式的區(qū)別只是在于把創(chuàng)建方法實(shí)現(xiàn)成什么方式涧黄,工廠方法模式是把創(chuàng)建延遲到子類(lèi)進(jìn)行,抽象工廠模式就是一系列工廠方法的組合赋荆。
它們分別解決不同的問(wèn)題笋妥,簡(jiǎn)單工廠和靜態(tài)工廠主要解決的是類(lèi)創(chuàng)建不統(tǒng)一,重復(fù)代碼窄潭,工廠方法主要解決的是對(duì)不同類(lèi)別可以創(chuàng)建不同的同類(lèi)實(shí)例春宣,抽象工廠主要解決的問(wèn)題是對(duì)一系列工廠方法的封裝,流程上的規(guī)范擴(kuò)展嫉你。
不登高山月帝,不知天之高也;不臨深溪幽污,不知地之厚也
感謝指點(diǎn)嚷辅、交流、喜歡