我正在学习 golang,并且被困在一个非常简单的概念上。也许是我的面向对象习惯使我的理解变得模糊,但我似乎无法让这个简单的例子起作用:
package main
import (
"fmt"
)
type datafield struct {
name string
value string
}
func (d datafield) NewField(name, value string) *datafield {
retval := new(datafield)
retval.name = name
retval.value = value
return retval
}
func main() {
field := datafield.NewField("name", "value")
if field == nil {
fmt.Println("Error: Did not create a datafield")
} else {
fmt.Println("Success!")
}
}
Run Code Online (Sandbox Code Playgroud)
错误是:
prog.go:20:29: not enough arguments in call to method expression datafield.NewField
have (string, string)
want (datafield, string, string)
Run Code Online (Sandbox Code Playgroud)
NewField(string,string)创建数据字段的正确方法是什么?
Go 并不完全是面向对象的语言并促进了简单性,这就是为什么之前的答案专注于修复您的代码。不过,如果您真的需要在 Go 中实现这种设计模式,请进一步阅读。
工厂方法模式是一种创建模式,它使用工厂方法来处理创建对象的问题,而无需指定将要创建的对象的确切类。这是通过调用工厂方法创建对象来完成的。(维基百科)
这是 Svetlin Ralchev 在 Go 中的另一个定义和一个非常好的例子:
工厂方法模式用于定义用于创建对象的运行时接口。之所以称为工厂,是因为它创建了各种类型的对象,而不必知道它创建的是哪种对象或如何创建它。(Golang 中的设计模式:工厂方法)
我已经扩展了您的示例以演示使用工厂方法的好处,因为如果您正在处理一个结构(OO 世界中的对象),则根本不需要使用工厂。 https://goplay.space/#SOXPmM86GgF
package main
import (
"fmt"
)
type dataField interface {
Print()
}
type dataField1 struct {
name string
value string
}
func (df *dataField1) Print() {
fmt.Println("dataField1 ->", df.name, ":", df.value)
}
type dataField2 struct {
name string
value string
}
func (df *dataField2) Print() {
fmt.Println("dataField2 ->", df.name, ":", df.value)
}
type dataFieldFactory interface {
Create(name, value string) dataField
}
type dataField1Factory struct{}
func (factory *dataField1Factory) Create(name, value string) dataField {
return &dataField1{
name: name,
value: value,
}
}
type dataField2Factory struct{}
func (factory *dataField2Factory) Create(name, value string) dataField {
return &dataField2{
name: name,
value: value,
}
}
type Document struct {
dataFieldFactories []dataFieldFactory
allValues [][]string
}
func (doc *Document) Print() {
for i, factory := range doc.dataFieldFactories {
field := factory.Create(doc.allValues[i][0], doc.allValues[i][1])
field.Print()
}
}
func main() {
doc := &Document{
dataFieldFactories: []dataFieldFactory{
&dataField1Factory{},
&dataField2Factory{},
},
allValues: [][]string{{"name1", "value1"}, {"name2", "value2"}},
}
doc.Print()
}
Run Code Online (Sandbox Code Playgroud)
该程序只是打印这个
dataField1 -> name1 : value1
dataField2 -> name2 : value2
Run Code Online (Sandbox Code Playgroud)
但是,如果您查看 main func,您不会发现任何具体类型dataField1和dataField2. 所有的复杂都隐藏在背后dataFieldFactories。双方dataField1Factory并dataField2Factory实现Create界面,返回的dataField接口,这两个具体的类型也实现了。因此,您可以调用Print()每种具体类型。
Document.Print()使用“创建”和“打印”界面打印出所有字段,而无需了解这些字段的实际创建或打印方式。我们通过向文档结构(对象)提供工厂方法(dataField1Factory{}和dataField2Factory{})列表和相应的字符串值来实现这一点。
请原谅我举一个有点人为的例子,但我希望,你会明白基本的想法。正如您所看到的,Go 允许您实现您熟悉的设计模式,这可能与您在纯 OO 语言中习惯的方式不同。