Golang设计模式-创建型-工厂方法

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 830 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 工厂方法的优缺点

  • 优点
    • 工厂类的功能通过继承的方式得到了分解,避免简单工厂逻辑过于复杂的问题;
    • 添加新的产品时只需要派生新的工厂和产品子类,而不需要修改原有工厂和产品的逻辑,符合开放-封闭原则。
  • 缺点
    • 工厂方法虽然分解了工厂逻辑,但客户端却需要参与产品类型的选择,即把原来简单工厂的复杂逻辑部分分担给了客户端。

完整代码:工厂方法

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