C語言中文網 目錄

Go語言工廠模式自動注冊——管理多個包的結構體

< 上一頁Go語言import導入包 Go語言并發下一頁 >

本例利用包的 init 特性,將 cls1 和 cls2 兩個包注冊到工廠,使用字符串創建這兩個注冊好的結構實例。

完整代碼的結構如下:

.
└── src
    └── chapter08
        └── clsfactory
            ├── main.go
            └── base
                └── factory.go
            └── cls1
                └── reg.go
            └── cls2
                └── reg.go

本套教程所有源碼下載地址:https://pan.baidu.com/s/1ORFVTOLEYYqDhRzeq0zIiQ    提取密碼:hfyf
類工廠(具體文件:…/chapter08/clsfactory/base/factory.go)
package base

// 類接口
type Class interface {
    Do()
}

var (
// 保存注冊好的工廠信息
    factoryByName = make(map[string]func() Class)
)

// 注冊一個類生成工廠
func Register(name string, factory func() Class) {
    factoryByName[name] = factory
}

// 根據名稱創建對應的類
func Create(name string) Class {
    if f, ok := factoryByName[name]; ok {
        return f()
    } else {
        panic("name not found")
    }
}
這個包叫base,負責處理注冊和使用工廠的基礎代碼,該包不會引用任何外部的包。

以下是對代碼的說明:
  • 第 4 行定義了“產品”:類。
  • 第 10 行使用了一個 map 保存注冊的工廠信息。
  • 第 14 行提供給工廠方注冊使用,所謂的“工廠”,就是一個定義為func() Class的普通函數,調用此函數,創建一個類實例,實現的工廠內部結構體會實現 Class 接口。
  • 第 19 行定義通過名字創建類實例的函數,該函數會在注冊好后調用。
  • 第 20 行在已經注冊的信息中查找名字對應的工廠函數,找到后,在第 21 行調用并返回接口。
  • 第 23 行是如果創建的名字沒有找到時,報錯。

類1及注冊代碼(具體文件:…/chapter08/clsfactory/cls1/reg.go)
package cls1

import (
    "chapter08/clsfactory/base"
    "fmt"
)

// 定義類1
type Class1 struct {
}

// 實現Class接口
func (c *Class1) Do() {
    fmt.Println("Class1")
}

func init() {

    // 在啟動時注冊類1工廠
    base.Register("Class1", func() base.Class {
        return new(Class1)
    })
}
上面的代碼展示了Class1的工廠及產品定義過程。
  • 第 9~15 行定義 Class1 結構,該結構實現了 base 中的 Class 接口。
  • 第 20 行,Class1 結構的實例化過程叫 Class1 的工廠,使用 base.Register() 函數在 init() 函數被調用時與一個字符串關聯,這樣,方便以后通過名字重新調用該函數并創建實例。

類2及注冊代碼(具體文件:…/chapter08/clsfactory/cls2/reg.go)
package cls2

import (
    "chapter08/clsfactory/base"
    "fmt"
)

// 定義類2
type Class2 struct {
}

// 實現Class接口
func (c *Class2) Do() {
    fmt.Println("Class2")
}

func init() {

    // 在啟動時注冊類2工廠
    base.Register("Class2", func() base.Class {
        return new(Class2)
    })
}
Class2 的注冊與 Class1 的定義和注冊過程類似。

類工程主流程(具體文件:…/chapter08/clsfactory/main.go)
package main

import (
    "chapter08/clsfactory/base"
    _ "chapter08/clsfactory/cls1"  // 匿名引用cls1包, 自動注冊
    _ "chapter08/clsfactory/cls2"  // 匿名引用cls2包, 自動注冊
)

func main() {

    // 根據字符串動態創建一個Class1實例
    c1 := base.Create("Class1")
    c1.Do()

    // 根據字符串動態創建一個Class2實例
    c2 := base.Create("Class2")
    c2.Do()

}
下面是對代碼的說明:
  • 第 5 和第 6 行使用匿名引用方法導入了 cls1 和 cls2 兩個包。在 main() 函數調用前,這兩個包的 init() 函數會被自動調用,從而自動注冊 Class1 和 Class2。
  • 第 12 和第 16 行,通過 base.Create() 方法查找字符串對應的類注冊信息,調用工廠方法進行實例創建。
  • 第 13 和第 17 行,調用類的方法。

執行下面的指令進行編譯:

export GOPATH=/home/davy/golangbook/code
go install chapter08/clsfactory
$GOPATH/bin/clsfactory

代碼輸出如下:
Class1
Class2
< 上一頁Go語言import導入包 Go語言并發下一頁 >

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo