Go 語(yǔ)言實(shí)現(xiàn)創(chuàng)建型設(shè)計(jì)模式 - 工廠模式
?01 介紹
工廠模式是一種創(chuàng)建型設(shè)計(jì)模式,包含三種類(lèi)型,分別是簡(jiǎn)單工廠、工廠方法和抽象工廠。
在《設(shè)計(jì)模式》[1]一書(shū)中,因?yàn)?nbsp;GoF[2] 認(rèn)為簡(jiǎn)單工廠是工廠方法的一種特例,所以 GoF 把工廠模式分為兩種類(lèi)型,分別是工廠方法和抽象工廠。
本文我們使用第一種分類(lèi)方式,分別介紹一下工廠模式的三種類(lèi)型。
02 使用場(chǎng)景
在介紹工廠模式的使用場(chǎng)景之前,我們需要先簡(jiǎn)單了解工廠模式的組成結(jié)構(gòu),一般分為抽象產(chǎn)品、具體產(chǎn)品、抽象工廠和具體工廠。
注意:簡(jiǎn)單工廠模式,不區(qū)分抽象工廠和具體工廠。
簡(jiǎn)單工廠
簡(jiǎn)單工廠適用于具體產(chǎn)品較少,且不會(huì)頻繁添加具體產(chǎn)品的場(chǎng)景。因?yàn)槊慷嘁粋€(gè)具體產(chǎn)品,在工廠中就多一個(gè) if 分支。
工廠方法
工廠方法適用于具體產(chǎn)品較多,且需要頻繁添加具體產(chǎn)品的場(chǎng)景。使用工廠方法可以避免使用 if 分支,當(dāng)我們需要添加具體產(chǎn)品時(shí),只需創(chuàng)建新的具體產(chǎn)品和具體工廠,符合開(kāi)閉原則和單一職責(zé)原則。
而且還可以將每個(gè)具體產(chǎn)品的創(chuàng)建邏輯拆分到不同的工廠中,避免使用一個(gè)工廠導(dǎo)致的代碼過(guò)于復(fù)雜。
注意:拆分多個(gè)工廠,則需要維護(hù)多個(gè)工廠的代碼。
抽象工廠
抽象工廠適用于一個(gè)具體工廠需要負(fù)責(zé)生產(chǎn)多個(gè)不同產(chǎn)品,并且工廠的職責(zé)不會(huì)繼續(xù)增加的場(chǎng)景(即抽象工廠定義的一組方法不會(huì)繼續(xù)增加)。
否則,不僅所有具體工廠都需要修改,抽象產(chǎn)品和具體產(chǎn)品也需要修改,違反開(kāi)閉原則。
03 實(shí)現(xiàn)方式
簡(jiǎn)單工廠
簡(jiǎn)單工廠模式違反了開(kāi)閉原則,嚴(yán)格意義上不算是一個(gè)設(shè)計(jì)模式,它主要包括三個(gè)結(jié)構(gòu),分別是工廠、抽象產(chǎn)品和具體產(chǎn)品。
- 工廠 - 負(fù)責(zé)調(diào)用具體產(chǎn)品生產(chǎn)產(chǎn)品,返回值是抽象產(chǎn)品(接口)。
- 抽象產(chǎn)品 - 負(fù)責(zé)定義產(chǎn)品,接口類(lèi)型,包含一組方法。
- 具體產(chǎn)品 - 負(fù)責(zé)被工廠調(diào)用,實(shí)現(xiàn)抽象產(chǎn)品(接口)。
工廠方法
工廠方法模式符合開(kāi)閉原則,它相比簡(jiǎn)單工廠模式,多了一個(gè)抽象工廠的結(jié)構(gòu),總共包括四個(gè)結(jié)構(gòu),分別是抽象工廠、具體工廠、抽象產(chǎn)品和具體產(chǎn)品。
- 抽象工廠(單個(gè)) - 負(fù)責(zé)定義工廠,接口類(lèi)型,包含一組方法。
- 具體工廠(多個(gè)) - 負(fù)責(zé)通過(guò)實(shí)例化具體產(chǎn)品創(chuàng)建產(chǎn)品,實(shí)現(xiàn)抽象工廠(接口)。
- 抽象產(chǎn)品(單個(gè)) - 負(fù)責(zé)定義產(chǎn)品,接口類(lèi)型,包含一組方法。
- 具體產(chǎn)品(多個(gè)) - 負(fù)責(zé)被具體工廠調(diào)用,實(shí)現(xiàn)抽象產(chǎn)品(接口)。
注意:此處“抽象工廠”是工廠方法模式中的一個(gè)結(jié)構(gòu),不要與抽象工廠模式混淆。
抽象工廠
抽象工廠模式也是總共包括四個(gè)結(jié)構(gòu),它與工廠方法模式不同,工廠方法模式中抽象產(chǎn)品只有一個(gè),而抽象工廠模式抽象產(chǎn)品有多個(gè)。
但是,四個(gè)結(jié)構(gòu)的職責(zé)與工廠方法模式相同。
- 抽象工廠(單個(gè))
- 具體工廠(多個(gè))
- 抽象產(chǎn)品(多個(gè))
- 具體產(chǎn)品(多個(gè))
04 Go 實(shí)現(xiàn)
簡(jiǎn)單工廠
閱讀上面這段代碼,我們可以發(fā)現(xiàn),我們通過(guò)代碼定義簡(jiǎn)單工廠模式的三個(gè)結(jié)構(gòu)。
定義一個(gè)包含一組方法的 IDrink 接口,代表抽象產(chǎn)品;
定義一個(gè) CocaCola? 結(jié)構(gòu)體和一個(gè) Sprite? 結(jié)構(gòu)體,并都實(shí)現(xiàn) IDrink 接口,代表具體產(chǎn)品;
定義一個(gè) SimpleFactory? 結(jié)構(gòu)體,并定義一個(gè)返回值是 IDrink? 的 Produce 方法,代表工廠。
工廠方法
閱讀上面這段代碼,我們通過(guò)代碼定義工廠方法模式的四個(gè)結(jié)構(gòu)。
定義一個(gè)包含一組方法的 IDrink 接口,代表抽象產(chǎn)品;
定義一個(gè) CocaCola? 結(jié)構(gòu)體和一個(gè) Sprite? 結(jié)構(gòu)體,并都實(shí)現(xiàn) IDrink 接口,代表具體產(chǎn)品;
定義一個(gè)包含一組方法的 IFactory 接口,代表抽象工廠;
定義一個(gè) CocaColaFactory? 結(jié)構(gòu)體和一個(gè) SpriteFactory? 結(jié)構(gòu)體,并都實(shí)現(xiàn) IFactory 接口,代表具體工廠;
抽象工廠
閱讀上面這段代碼,我們通過(guò)代碼定義抽象工廠模式的四個(gè)結(jié)構(gòu)。
定義一個(gè)包含一組方法的 AbstractCola? 接口,和一個(gè)包含一組方法的 AbstractSprite 接口,均代表抽象產(chǎn)品(多個(gè)抽象產(chǎn)品);
定義一個(gè) CocaBrandCola? 結(jié)構(gòu)體,實(shí)現(xiàn) AbstractCola? 接口;定義一個(gè) CocaBrandSprite? 結(jié)構(gòu)體,實(shí)現(xiàn) AbstractSprite 接口;均代表具體產(chǎn)品(多個(gè)具體產(chǎn)品);
定義一個(gè)包含一組方法的 AbstractFactory 接口,代表抽象工廠;
定義一個(gè) CocaFactory? 結(jié)構(gòu)體,實(shí)現(xiàn) AbstractFactory? 接口;定義一個(gè) PepsiFactory? 結(jié)構(gòu)體,實(shí)現(xiàn) AbstractFactory 接口;均代表具體工廠(多個(gè)具體工廠);
05 總結(jié)
本文介紹的三種工廠模式中,簡(jiǎn)單工廠和工廠方法比較常用,抽象工廠使用較少。
其中,簡(jiǎn)單工廠適用于具體產(chǎn)品較少,且不會(huì)頻繁添加具體產(chǎn)品的場(chǎng)景;
工廠方法適用于具體產(chǎn)品較多,且需要頻繁添加具體產(chǎn)品的場(chǎng)景;
還有就是生產(chǎn)具體產(chǎn)品,代碼比較復(fù)雜,不只是實(shí)例化具體產(chǎn)品,還需要其他業(yè)務(wù)邏輯的場(chǎng)景;
或不希望代碼中使用一堆 if 分支的場(chǎng)景。
參考資料
?[1]《設(shè)計(jì)模式》: https://en.wikipedia.org/wiki/Design_Patterns
[2]GoF: http://wiki.c2.com/?GangOfFour