前言
前面我們學(xué)習(xí)了相對(duì)簡(jiǎn)單的 原型模式 今天就讓我們一起來(lái)學(xué)習(xí)下另外一個(gè)很簡(jiǎn)單的模式:簡(jiǎn)單工廠模式
按照慣例我們先看下工廠的概念:
工廠:又稱制造廠怠惶,是一所用以生產(chǎn)貨物的大型工業(yè)樓宇。大部分工廠皆設(shè)有以大型機(jī)器或設(shè)備構(gòu)成的生產(chǎn)線。
解決了什么問(wèn)題:
我們都知道计济,現(xiàn)實(shí)中的工廠解決的是生產(chǎn)力低下的問(wèn)題唐全。那軟件中的工廠呢安券?
軟件中的工廠其實(shí)跟現(xiàn)實(shí)中的工廠很像悉盆,都是為了解決創(chuàng)建產(chǎn)品的問(wèn)題。
現(xiàn)實(shí)中的工廠典唇,我們?nèi)舆M(jìn)去材料镊折,工廠生產(chǎn)成產(chǎn)品,我們不需要管他怎么生產(chǎn)的只要拿到最后的產(chǎn)品就行了介衔。
軟件里的工廠恨胚,我們?nèi)舆M(jìn)去參數(shù),工廠生產(chǎn)出來(lái)對(duì)象夜牡,我們也不需要中的他是怎么實(shí)例化的与纽,只要最后拿到相應(yīng)對(duì)象就行了侣签。
GOF在《設(shè)計(jì)模式》一書(shū)中將工廠模式分為兩類:工廠方法模式(Factory Method)與抽象工廠模式(Abstract Factory)。
將簡(jiǎn)單工廠模式(Simple Factory)看為工廠方法模式的一種特例急迂,兩者歸為一類影所。今天我們就先條軟柿子捏,從簡(jiǎn)單工廠模式入手僚碎。
按照慣例我們先擺出今天的內(nèi)容要點(diǎn):
通過(guò)這篇文章你能學(xué)到什么
(建議你可以帶著問(wèn)題去學(xué)習(xí))
1猴娩、簡(jiǎn)單工廠模式的定義;
2勺阐、簡(jiǎn)單工廠模式的寫(xiě)法卷中;
3、簡(jiǎn)單工廠模式的使用場(chǎng)景渊抽;
4蟆豫、簡(jiǎn)單工廠模式的優(yōu)缺點(diǎn);
上面我們已經(jīng)了解了簡(jiǎn)單工廠的概念和工廠在日常生活中的解釋懒闷,我們?cè)賮?lái)看軟件工程中簡(jiǎn)單工廠模式的定義:
簡(jiǎn)單工廠模式(Simple Factory Pattern):定義一個(gè)工廠類十减,它可以根據(jù)參數(shù)的不同返回不同類的實(shí)例,被創(chuàng)建的實(shí)例通常都具有共同的父類愤估。因?yàn)樵诤?jiǎn)單工廠模式中用于創(chuàng)建實(shí)例的方法是靜態(tài)(static)方法帮辟,因此簡(jiǎn)單工廠模式又被稱為靜態(tài)工廠方法(Static Factory Method)模式,它屬于類創(chuàng)建型模式玩焰。
我們一起來(lái)分析一下簡(jiǎn)單工廠模式的定義由驹,可以看到,簡(jiǎn)單工廠模式的要點(diǎn)在于:
當(dāng)你當(dāng)你需要什么昔园,只需要傳入一個(gè)正確的參數(shù)蔓榄,就可以獲取你所需要的對(duì)象,而無(wú)須知道其創(chuàng)建細(xì)節(jié)默刚。簡(jiǎn)單工廠模式結(jié)構(gòu)比較簡(jiǎn)單润樱,其核心是工廠類的設(shè)計(jì)。
簡(jiǎn)單解釋就是:我給你傳參羡棵,你給我對(duì)象。我不需要管你是怎么創(chuàng)建的嗅钻。
簡(jiǎn)單工程模式的類圖
簡(jiǎn)單工廠模式的類圖如下:
通過(guò)類圖我們可以看到皂冰,簡(jiǎn)單工廠模式主要是有三個(gè)角色:Factory(工廠角色)、Product(抽象產(chǎn)品角色)养篓、ConcreteProduct(具體產(chǎn)品角色)秃流,接下來(lái)我們先分別認(rèn)識(shí)一下這三個(gè)角色:
Factory(工廠角色):工廠角色即工廠類,它是簡(jiǎn)單工廠模式的核心柳弄,負(fù)責(zé)實(shí)現(xiàn)創(chuàng)建所有產(chǎn)品實(shí)例的內(nèi)部邏輯舶胀;工廠類可以被外界直接調(diào)用概说,創(chuàng)建所需的產(chǎn)品對(duì)象;在工廠類中提供了靜態(tài)的工廠方法factoryMethod()嚣伐,它的返回類型為抽象產(chǎn)品類型Product糖赔。
Product(抽象產(chǎn)品角色):它是工廠類所創(chuàng)建的所有對(duì)象的父類,封裝了各種產(chǎn)品對(duì)象的公有方法轩端,它的引入將提高系統(tǒng)的靈活性放典,使得在工廠類中只需定義一個(gè)通用的工廠方法,因?yàn)樗袆?chuàng)建的具體產(chǎn)品對(duì)象都是其子類對(duì)象基茵。
ConcreteProduct(具體產(chǎn)品角色):它是簡(jiǎn)單工廠模式的創(chuàng)建目標(biāo)奋构,所有被創(chuàng)建的對(duì)象都充當(dāng)這個(gè)角色的某個(gè)具體類的實(shí)例。每一個(gè)具體產(chǎn)品角色都繼承了抽象產(chǎn)品角色拱层,需要實(shí)現(xiàn)在抽象產(chǎn)品中聲明的抽象方法弥臼。
看完類圖和成員介紹不知道大家有沒(méi)有對(duì)簡(jiǎn)單工廠模式有一個(gè)更深刻的認(rèn)識(shí)?
什么還沒(méi)有根灯,好吧径缅。那接下來(lái)我們通過(guò)一個(gè)具體的代碼例子來(lái)加深一下印象。
簡(jiǎn)單的例子
我們都知道可口可樂(lè)公司生產(chǎn)了很多飲料箱吕,雪碧芥驳、芬達(dá)、肥仔快樂(lè)水等茬高;那這些飲料肯定都是通過(guò)飲料工廠來(lái)生產(chǎn)的兆旬,那我們就用簡(jiǎn)單工廠模式來(lái)實(shí)現(xiàn)一下這個(gè)場(chǎng)景:
抽象產(chǎn)品:Produce —— 飲料
具體產(chǎn)品:ConcreteProduct —— 具體飲料
工廠:Factory —— 飲料工廠
/**
* @description: 飲料——抽象產(chǎn)品
*/
interface BeveragesProduct {
/**
* @description: 獲取飲料名稱
* @date:
* @company:
* @author: Meteor
*/
fun getBeveragesName()
/**
* @description: 設(shè)置飲料配方
* @date:
* @company:
* @author: Meteor
*/
fun getBeveragesRecipe()
}
/**
* @description: 可樂(lè) —— 具體產(chǎn)品
*/
class Coke : BeveragesProduct {
override fun getBeveragesName() {
println("我是可樂(lè):別名肥仔快樂(lè)水")
}
override fun getBeveragesRecipe() {
println("配方:水,二氧化碳怎栽,可樂(lè)糖漿")
}
}
/**
* @description: 芬達(dá) —— 具體產(chǎn)品
*/
class Fanta :BeveragesProduct{
override fun getBeveragesName() {
println("我是芬達(dá)")
}
override fun getBeveragesRecipe() {
println("配方:水丽猬,二氧化碳,芬達(dá)糖漿")
}
}
/**
* @description: 雪碧 —— 具體產(chǎn)品
*/
class Sprite : BeveragesProduct {
override fun getBeveragesName() {
println("我是雪碧")
}
override fun getBeveragesRecipe() {
println("配方:水熏瞄,二氧化碳脚祟,雪碧糖漿")
}
}
/**
* @description: 飲料工廠 —— 工廠
*/
class BeveragesFactory {
companion object {
val TYPE_COKE = 1
val TYPE_FANTA = 2
val TYPE_SPRITE = 3
fun getBeverages(type: Int): BeveragesProduct? {
var beveragesProduct: BeveragesProduct? = null
when (type) {
TYPE_COKE -> {
beveragesProduct = Coke()
}
TYPE_FANTA -> {
beveragesProduct = Fanta()
}
TYPE_SPRITE -> {
beveragesProduct = Sprite()
}
}
return beveragesProduct
}
}
}
/**
* @description: 肥仔,老喝碳酸飲料
*/
class Fatty {
companion object {
@JvmStatic
fun main(args: Array<String>) {
//通過(guò)往工廠傳類型强饮,獲取具體對(duì)象
val beveragesProduct: BeveragesProduct? = BeveragesFactory.getBeverages(BeveragesFactory.TYPE_COKE)
beveragesProduct?.getBeveragesName()
beveragesProduct?.getBeveragesRecipe()
}
}
}
工作中使用的場(chǎng)景
簡(jiǎn)單工廠模式在工作中有很多應(yīng)用的地方由桌,具體在哪里使用,參照下面兩個(gè)因素就可以了:
1邮丰、工廠類負(fù)責(zé)創(chuàng)建的對(duì)象比較少行您,由于創(chuàng)建的對(duì)象較少,不會(huì)造成工廠方法中的業(yè)務(wù)邏輯太過(guò)復(fù)雜剪廉。
2娃循、客戶端只知道傳入工廠類的參數(shù),對(duì)于如何創(chuàng)建對(duì)象并不關(guān)心斗蒋。
優(yōu)點(diǎn)
簡(jiǎn)單工廠模式的優(yōu)點(diǎn)主要有以下幾點(diǎn):
1捌斧、 工廠類包含必要的判斷邏輯笛质,可以決定在什么時(shí)候創(chuàng)建哪一個(gè)產(chǎn)品類的實(shí)例,客戶端可以免除直接創(chuàng)建產(chǎn)品對(duì)象的職責(zé)捞蚂,而僅僅“消費(fèi)”產(chǎn)品妇押,簡(jiǎn)單工廠模式實(shí)現(xiàn)了對(duì)象創(chuàng)建和使用的分離。
2洞难、 客戶端無(wú)須知道所創(chuàng)建的具體產(chǎn)品類的類名舆吮,只需要知道具體產(chǎn)品類所對(duì)應(yīng)的參數(shù)即可,對(duì)于一些復(fù)雜的類名队贱,通過(guò)簡(jiǎn)單工廠模式可以在一定程度減少使用者的記憶量色冀。
3、通過(guò)引入配置文件柱嫌,可以在不修改任何客戶端代碼的情況下更換和增加新的具體產(chǎn)品類锋恬,在一定程度上提高了系統(tǒng)的靈活性。
缺點(diǎn)
當(dāng)然簡(jiǎn)單工廠模式也有它的缺點(diǎn):
1编丘、由于工廠類集中了所有產(chǎn)品的創(chuàng)建邏輯与学,職責(zé)過(guò)重,一旦不能正常工作嘉抓,整個(gè)系統(tǒng)都要受到影響索守。
2、使用簡(jiǎn)單工廠模式勢(shì)必會(huì)增加系統(tǒng)中類的個(gè)數(shù)(引入了新的工廠類)抑片,增加了系統(tǒng)的復(fù)雜度和理解難度卵佛。
3、系統(tǒng)擴(kuò)展困難敞斋,一旦添加新產(chǎn)品就不得不修改工廠邏輯截汪,在產(chǎn)品類型較多時(shí),有可能造成工廠邏輯過(guò)于復(fù)雜植捎,不利于系統(tǒng)的擴(kuò)展和維護(hù)衙解。
4、簡(jiǎn)單工廠模式由于使用了靜態(tài)工廠方法焰枢,造成工廠角色無(wú)法形成基于繼承的等級(jí)結(jié)構(gòu)蚓峦。
總結(jié)
其實(shí)簡(jiǎn)單工廠模式還是相對(duì)比較好理解的,通俗點(diǎn)說(shuō)就是把我們之前各種通過(guò) if 判斷后創(chuàng)建的對(duì)象济锄,封裝了起來(lái)(因?yàn)楣S里面也是通過(guò)if判斷的)枫匾,不過(guò)把這塊單獨(dú)抽離了出來(lái),做了解耦方便我們維護(hù)和管理拟淮。
簡(jiǎn)單工廠模式屬于工廠模式和抽象工廠模式的基礎(chǔ),先學(xué)好這個(gè)對(duì)學(xué)習(xí)后面兩個(gè)有幫助谴忧。
設(shè)計(jì)模式目錄
設(shè)計(jì)模式(一)—— 認(rèn)識(shí)設(shè)計(jì)模式
設(shè)計(jì)模式(二)—— 技術(shù)直男正確“面向?qū)ο蟆钡牧笤瓌t
設(shè)計(jì)模式(三)—— 單例模式
設(shè)計(jì)模式(四)—— 原型模式
設(shè)計(jì)模式(五)—— 簡(jiǎn)單工廠模式
參考資料
《設(shè)計(jì)模式——可復(fù)用面向?qū)ο筌浖幕A(chǔ)》
《Head First設(shè)計(jì)模式》
《大話設(shè)計(jì)模式》
《設(shè)計(jì)模式之禪》
《Android 源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)》