1 引例
仍然是漢堡的故事,在Golang設計模式-創建型-簡單工廠 一文中,我們提到簡單工廠的缺點之一是當產品種類較多時,工廠邏輯會變得非常複雜。哪裏複雜,我們就分解哪裏,這是分治法最樸素的思想,既然工廠邏輯複雜,那我們就把它分解一下吧。
2 工廠方法
2.1 定義
工廠方法通過定義一個工廠基類和產品基類,並派生相應的工廠和產品子類的方式,實現由具體工廠生產具體產品的目標。
2.2 工廠方法三要素
工廠系列的模式(簡單工廠、工廠方法,以及我們馬上將要介紹的抽象工廠)都有三要素,即產品、工廠和客戶端。
2.2.1 產品
與簡單工廠相同,抽象產品即爲漢堡,我們在此基礎上派生出KFC和McDonalds的具體漢堡。
type Hamburger interface {
Deliver()
}
type KfcHamburger struct{}
func (h KfcHamburger) Deliver() {
fmt.Println("This is a hamburger from KFC.\n")
}
type McdonaldsHamburger struct{}
func (h McdonaldsHamburger) Deliver() {
fmt.Println("This is a hamburger from McDonalds.\n")
}
2.2.2 工廠
與簡單工廠模式由一個工廠完成所有產品的創建不同,工廠方法定義了一個抽象的工廠基類,並由派生的具體工廠負責對應產品的生產。
type HamburgerFactory interface {
Create() Hamburger
}
type Kfc struct{}
func (f Kfc) Create() Hamburger {
return new(KfcHamburger)
}
type Mcdonalds struct{}
func (f Mcdonalds) Create() Hamburger {
return new(McdonaldsHamburger)
}
2.2.3 客戶端
也就是通知工廠生產漢堡的人啦。
func main() {
prefer := getPreferHamburger()
var factory HamburgerFactory
switch prefer {
case "KFC":
factory = new(Kfc)
case "McDonalds":
factory = new(Mcdonalds)
default:
fmt.Printf("%s not supported yet.\n", prefer)
os.Exit(1)
}
hamburger := factory.Create()
hamburger.Deliver()
}
我們來測試一下吧:
$ go build -o factory_method.bin factory_method.go
$ ll factory_method.bin
-rwxrwxr-x 1 pirlo pirlo 1672879 8月 30 21:39 factory_method.bin*
$ ./factory_method.bin -prefer KFC
This is a hamburger from KFC.
$ ./factory_method.bin -prefer McDonalds
This is a hamburger from McDonalds.
使用類圖表示如下:
2.3 工廠方法的優缺點
- 優點
- 工廠類的功能通過繼承的方式得到了分解,避免簡單工廠邏輯過於複雜的問題;
- 添加新的產品時只需要派生新的工廠和產品子類,而不需要修改原有工廠和產品的邏輯,符合開放-封閉原則。
- 缺點
- 工廠方法雖然分解了工廠邏輯,但客戶端卻需要參與產品類型的選擇,即把原來簡單工廠的複雜邏輯部分分擔給了客戶端。
完整代碼:工廠方法