2015-05-07 46 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

相关问题