只一篇就夠了·設(shè)計(jì)模式(1) - 工廠模式

工廠模式屬于創(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)嚷辅、交流、喜歡

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末距误,一起剝皮案震驚了整個(gè)濱河市簸搞,隨后出現(xiàn)的幾起案子扁位,更是在濱河造成了極大的恐慌,老刑警劉巖趁俊,帶你破解...
    沈念sama閱讀 216,470評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件域仇,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡寺擂,警方通過(guò)查閱死者的電腦和手機(jī)暇务,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)怔软,“玉大人垦细,你說(shuō)我怎么就攤上這事〉脖疲” “怎么了括改?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,577評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)挚瘟。 經(jīng)常有香客問(wèn)我叹谁,道長(zhǎng)饲梭,這世上最難降的妖魔是什么乘盖? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,176評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮憔涉,結(jié)果婚禮上订框,老公的妹妹穿的比我還像新娘。我一直安慰自己兜叨,他們只是感情好穿扳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,189評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著国旷,像睡著了一般矛物。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上跪但,一...
    開(kāi)封第一講書(shū)人閱讀 51,155評(píng)論 1 299
  • 那天履羞,我揣著相機(jī)與錄音,去河邊找鬼屡久。 笑死忆首,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的被环。 我是一名探鬼主播糙及,決...
    沈念sama閱讀 40,041評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼筛欢!你這毒婦竟也來(lái)了浸锨?” 一聲冷哼從身側(cè)響起唇聘,我...
    開(kāi)封第一講書(shū)人閱讀 38,903評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎揣钦,沒(méi)想到半個(gè)月后雳灾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冯凹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,539評(píng)論 2 332
  • 正文 我和宋清朗相戀三年谎亩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宇姚。...
    茶點(diǎn)故事閱讀 39,703評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡匈庭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出浑劳,到底是詐尸還是另有隱情阱持,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評(píng)論 5 343
  • 正文 年R本政府宣布魔熏,位于F島的核電站衷咽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蒜绽。R本人自食惡果不足惜镶骗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,013評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望躲雅。 院中可真熱鬧鼎姊,春花似錦、人聲如沸相赁。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,664評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)钮科。三九已至唤衫,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間绵脯,已是汗流浹背佳励。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,818評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桨嫁,地道東北人植兰。 一個(gè)月前我還...
    沈念sama閱讀 47,711評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像璃吧,于是被迫代替她去往敵國(guó)和親楣导。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,601評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 設(shè)計(jì)模式匯總 一畜挨、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用筒繁、多...
    MinoyJet閱讀 3,939評(píng)論 1 15
  • 簡(jiǎn)單工廠模式雖然簡(jiǎn)單噩凹,但存在一個(gè)很?chē)?yán)重的問(wèn)題。當(dāng)系統(tǒng)中需要引入新產(chǎn)品時(shí)毡咏,由于靜態(tài)工廠方法通過(guò)所傳入?yún)?shù)的不同來(lái)創(chuàng)建...
    justCode_閱讀 1,184評(píng)論 1 9
  • 一個(gè)UML類(lèi)圖 類(lèi)之間的關(guān)系 類(lèi)的繼承結(jié)構(gòu)表現(xiàn)在UML中為:泛化(generalize)與實(shí)現(xiàn)(realize) ...
    僚機(jī)KK閱讀 645評(píng)論 0 0
  • 設(shè)計(jì)原則: 要依賴(lài)抽象驮宴,不要依賴(lài)具體類(lèi) 目錄 本文的結(jié)構(gòu)如下: 什么是抽象工廠模式 為什么要用該模式 模式的結(jié)構(gòu) ...
    w1992wishes閱讀 1,112評(píng)論 0 6
  • 今天學(xué)習(xí)下最常見(jiàn)的工廠模式,工廠模式細(xì)分下來(lái)有三大類(lèi): 他們的目標(biāo)都是一樣的:封裝對(duì)象的創(chuàng)建呕缭。但是實(shí)現(xiàn)手段和使用場(chǎng)...
    西木柚子閱讀 2,148評(píng)論 7 28