Golang設計模式-創建型-簡單工廠

1 引例

李雷喜歡上了韓梅梅,他知道韓梅梅喜歡喫漢堡,於是就想買漢堡給她喫,但李雷不確定韓梅梅喜歡的是肯德基的漢堡還是麥當勞的漢堡,怎樣幫助他呢?
最直觀和最簡單的實現就是if+else:

if prefer == "KFC" {
    CreateKfcHamburger()
} else if prefer == "McDonalds" {
    CreateMcdonaldsHamburger()
}

這個實現的問題是客戶端關注了產品(漢堡)創建的全過程,且當擴展產品種類時需要修改客戶端代碼,違反了開放-封閉原則(對增加開放,對修改封閉)。
那麼有沒有更好的實現呢?

2 簡單工廠

2.1 定義

簡單工廠通過定義一個工廠類,並提供創建產品的方法,將客戶端從創建具體產品的尷尬局面中擺脫出來,客戶端只需要告知產品類型即可,產品的具體創建由工廠完成。

簡單工廠-定義

2.2 簡單工廠三要素

  • 產品: 客戶端需要的產品
  • 工廠: 生產產品的工廠
  • 客戶端: 消費產品的客戶

以引例的漢堡工廠爲例,產品即爲漢堡,這個是一個抽象類型,根據產品類型的不同,我們分別定義兩個具體產品,即肯德基的漢堡和麥當勞的漢堡:

type Hamburger interface {
    Deliver()
}

type KfcHamburger struct{}
func (h KfcHamburger) Deliver() {
    fmt.Println("This is a hamburger from KFC.")
}

type McdonaldsHamburger struct{}
func (h McdonaldsHamburger) Deliver() {
    fmt.Println("This is a hamburger from McDonalds.")
}

漢堡工廠則根據需要生產指定類型的漢堡:

type HamburgerFactory struct{}

func (f HamburgerFactory) CreateHamburger(prefer string) Hamburger {
    switch prefer {
    case "KFC":
        return new(KfcHamburger)
    case "McDonalds":
        return new(McdonaldsHamburger)
    default:
        return nil
    }
}

於是,客戶端再也不關注產品的具體創建過程了,而是告訴工廠“我需要什麼,你就給我生產什麼”:

func main() {

    prefer := getPreferHamburger()

    factory := new(creational.HamburgerFactory)
    hamburger := factory.CreateHamburger(prefer)
    if hamburger == nil {
        fmt.Printf("%s not supported yet.\n", prefer)
        os.Exit(1)
    }

    hamburger.Deliver()
}

李雷作爲客戶,只需要獲取韓梅梅喜歡的漢堡類型,然後讓工廠生產就可以了:

$ ./simple_factory.bin -prefer KFC
This is a hamburger from KFC.

$ ./simple_factory.bin -prefer McDonalds
This is a hamburger from McDonalds.

使用類圖表示如下:

簡單工廠-漢堡

2.3 簡單工廠的優缺點

  • 優點
    • 客戶端不關注產品的創建過程,避免客戶端邏輯的複雜;
    • 利於擴展新產品,且無需修改客戶端代碼。
  • 缺點
    • 當產品種類較多時,工廠邏輯會變得非常複雜;
    • 雖然新增產品時不需要修改客戶端實現,但仍然需要對工廠邏輯做調整,實際也不完全符合“開放-封閉”原則。

完整代碼: 簡單工廠

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章