2015-05-07 45 views
1

我試圖實現一個工廠函數,該函數將返回滿足接口X的合同的許多結構體之一的實例。如何在後續階段中將類型存儲在初始化映射中

m := make(map[string] ?) 
func init() { 
    m["a"] = ? 
    m["b"] = ? 
} 

type X interface { 
    y() 
} 

type A struct {} 
func (a * A) y() {} 

type B struct {} 
func (b * B) y() {} 


function factory(name string) X { 
    return &m[name]{} 
} 

上面的代碼只是一個簡單的我想要實現的示範 - 尋找這是否是可能的,或者如果有一個不同的去成語來解決這種要求,我」指針失蹤。

回答

2

可以使用map[string]X,與X中的接口(其可以參考值或任何物體尊重X合同的一個指針)

,或者如果有一個不同的去成語解決這種要求,即我丟了?

您還可以使用反射(如「Instance new Type」)來實現您的工廠。

reflect.New(yourtype).Elem().Interface() 

您可以在「is there a way to create an instance of a struct from a string?」中看到工廠示例。


用於工廠方法(每次返回一個新實例)越快的方法是使用一個開關(如in this example):

// Create a new Widget interface based on WidgetType and set WidgetInfo 
func New(wt WidgetType, wi WidgetInfo) Widget_iface { 
    switch wt { 
    case Widget_A: 
     return newWidgetA(wi) 
    case Widget_B: 
     return newWidgetB(wi) 
    } 
    return nil 
} 
+0

Thanks @VonC。看起來像使用實例註冊類型的額外開銷小,但我想這個實例將被合理快速地垃圾收集? –

+0

@ Ali-AkberSaifee是的,它會的。但總的來說,反射速度較慢,所以如果你打算每秒鐘撥打數百次的時間,地圖會更快。 – VonC

+0

@ Ali-AkberSaifee您希望您的工廠返回A或B的* new *實例嗎?如果是的話,我已經編輯了答案。 – VonC

1

如果有一個簡單的值類型,那麼作爲@VonC所述,您可以使用map[string]X並返回示例值的副本。

對於其他任何東西,而不是使用反射,我只是使用創建函數的地圖。像什麼image包與 image.RegisterFormat

E.g. (playground):

package main 

import "fmt" 

type X interface { 
     y() 
} 

type newXFunc func() X 

// Here just a map variable and two functions, but 
// this could be a type with two methods instead. 

var m = map[string]newXFunc{} 

func register(name string, fn newXFunc) { 
     m[name] = fn 
} 

func factory(name string) X { 
     return m[name]() 
} 

func init() { 
     // If register is exported than these 
     // calls can be in other packages that 
     // implement A and B. 
     register("a", NewA) 
     // For simple things that don't have/need 
     // their own stand-alone "new" function. 
     register("b", func() X { return B{} }) 
} 

type A struct{} 

func (a *A) y() {} 
func NewA() X { return &A{} } 

type B struct{} 

func (b B) y() {} 

func main() { 
     a1 := factory("a") 
     b1 := factory("b") 
     fmt.Printf("%T\n", a1) 
     fmt.Printf("%T\n", b1) 
} 
+0

功能的地圖比我的答案更有效。 +1 – VonC

相關問題