2016-01-22 70 views
-1

我想创建一个工厂方法,返回一个实现某个接口的结构的构造函数。去工厂方法返回类型接口,而不是实现接口的结构

下面是一些示例代码,说明我正在使用的模式。

// Generic Interface 
type Foo interface { 
    Bar() string 
} 

type FooConstructor func(name string) Foo 

// A struct that implements Foo 
type RealFoo struct { 
    Name string 
} 

func (f *RealFoo) Bar() string { 
    return f.Name 
} 

func NewRealFoo(name string) Foo { 
    return &RealFoo{Name: name} 
} 

// Factory method to return some FooConstructor 
func FooFactory() FooConstructor { 
    // based on some logic, return some Foo constructor 
    return NewRealFoo 
} 

func main() { 
    ff := FooFactory() 
    f := ff("baz") 
    fmt.Println(f.Bar()) 
    fmt.Println(f.Name) 
} 

http://play.golang.org/p/0RzXlIGAs8

当我尝试和未接口中定义我的结构进入一个领域,我得到一个错误:

f.Name undefined (type Foo has no field or method Name)

我相信问题是,我的构造函数func NewRealFoo(name string) Foo具有作为返回类型的接口,而不是*RealFoo。但为了将其用作工厂方法的FooConstructor类型,返回类型必须是Foo接口。

如何修复我的代码以便我可以访问该字段f.Name

+1

没有必要在Go中编程Java。 – Volker

+0

@Volker Go会有什么合适的设计模式? – adam

+1

这是一个奇怪的问题。设计模式有助于实现不能用语言自然表达的东西。你为什么认为你需要一个'FooFactory'?为什么你需要两次(在FooConstructor和FooFactory中)包装一个普通,简单,可理解的'NewRealFoo'?很可能有**没有**需要**;不是,也不是未来。例如。即使没有生产构造函数的工厂,测试工作也很好。 – Volker

回答

2

您实际上正在返回RealFoo对象,但作为Foo的实现。

要获得RealFoo结构领域中,使用类型断言:

f.(RealFoo).Name 

,或者为了避免恐慌,如果它不是一个RealFoo

if realFoo, ok := f.(RealFoo); ok { 
    _ := realFoo.Name 
} 

以上全部或部分开关可能的类型的Foo

switch rf := f.(type) { 
case realFoo: 
    _ := rf.Name // rf is a realFoo 
case unrealFoo: 
    _ := rf.ImaginaryName // rf is an unrealFoo 
case surrealFoo: 
    _ := rf.SurrealName // rf is a surrealFoo 
default: 
    // rf is none of the above types 
} 

的如果您愿意修改您的工厂构造函数,您还可以从NewRealFoo返回RealFoo,而不是Foo。由于它实现了该接口,因此在任何地方使用Foo仍然有效。在NewRealFoo中这是你正在做的,当在返回Foo的函数中返回RealFoo时。

func NewRealFoo(name string) RealFoo { 
    return &RealFoo{Name: name} 
} 
+0

这些建议是非常好的,但我试图避免使用类型转换,因为那样我就需要知道从工厂返回哪个具体的实现,从而破坏了工厂方法的目的。我认为我的问题是我试图访问一个领域,界面一无所知。如果它是所有实现中的一个字段,我应该将其封装在一个方法中,比如'f.Name()'并将其添加到接口中。 – adam

+0

你已经有'foo.Bar()'。你的问题的哪部分我没有回答? –