Go 实现常用设计模式(二)工厂模式

工厂模式

Posted by 果果 on October 19, 2021

由于 Go 中缺少类和继承等OOP特性, 所以无法使用Go来实现经典的工厂方法模式。 不过, 我们仍然能实现模式的基础版本, 即简单工厂。

在本例中, 我们将使用工厂结构体来构建多种类型的武器。

首先, 我们来创建一个名为iGun的接口, 其中将定义一支枪所需具备的所有方法。 然后是实现了iGun接口的 gun枪支结构体类型。 两种具体的枪支——ak47musket火枪——两者都嵌入了枪支结构体, 且间接实现了所有的iGun方法。

gunFactory枪支工厂结构体将发挥工厂的作用, 即通过传入参数构建所需类型的枪支。 main.go则扮演着客户端的角色。 其不会直接与ak47musket进行互动, 而是依靠gunFactory来创建多种枪支的实例, 仅使用字符参数来控制生产。

iGun.go: 产品接口

package main

type iGun interface {
    setName(name string)
    setPower(power int)
    getName() string
    getPower() int
}

gun.go: 具体产品

package main

type gun struct {
    name  string
    power int
}

func (g *gun) setName(name string) {
    g.name = name
}

func (g *gun) getName() string {
    return g.name
}

func (g *gun) setPower(power int) {
    g.power = power
}

func (g *gun) getPower() int {
    return g.power
}

ak47.go: 具体产品

package main

type ak47 struct {
    gun
}

func newAk47() iGun {
    return &ak47{
        gun: gun{
            name:  "AK47 gun",
            power: 4,
        },
    }
}

musket.go: 具体产品

package main

type musket struct {
	gun
}

func newMusket() iGun {
	return &musket{
		gun: gun{
			name:  "Musket gun",
			power: 1,
		},
	}
}

gunFactory.go: 工厂

package main

import "fmt"

func getGun(gunType string) (iGun, error) {
    if gunType == "ak47" {
        return newAk47(), nil
    }
    if gunType == "musket" {
        return newMusket(), nil
    }
    return nil, fmt.Errorf("Wrong gun type passed")
}

main.go: 客户端代码

package main

import "fmt"

func main() {
	ak47, _ := getGun("ak47")
	musket, _ := getGun("musket")

	printDetails(ak47)
	printDetails(musket)
}

func printDetails(g iGun) {
	fmt.Printf("Gun: %s", g.getName())
	fmt.Println()
	fmt.Printf("Power: %d", g.getPower())
	fmt.Println()
}

output.txt: 执行结果

Gun: AK47 gun
Power: 4
Gun: Musket gun
Power: 1