gpt4 book ai didi

go - 使用工厂模式时接口(interface)应该在哪里定义?

转载 作者:行者123 更新时间:2023-12-03 02:23:29 26 4
gpt4 key购买 nike

我正在使用工厂对象FooFactory创建 Foo 类型的实例其中有一些私有(private)数据成员。我使用工厂这样一个对象Bar它创建 Foo 的实例不需要提供(甚至知道)这些私有(private)数据成员:我首先使用必要的私有(private)内容配置工厂,然后给出 Bar这个配置的工厂。

我要Bar使用这些Foo通过接口(interface)的对象,这样我就可以使用 gomock 来模拟它们并测试 Bar正确使用它们。根据我所读到的关于 go 中接口(interface)的内容,最佳实践是在使用接口(interface)的地方定义接口(interface),而不是在定义底层类型的地方,所以我有一个 Fooer接口(interface)与我的Bar在同一个包中对象,以及Bar使用这个Fooer任何需要 Foo 的接口(interface)(或稍后, MockFoo )。

我也想要Bar使用FooFactory出于同样的原因通过接口(interface),所以我可以模拟它并断言它创建 Foo当我期望的时候对象。再次,我在Bar中定义了一个接口(interface)。 s包FooBuilder ,其中底层 FooFactory隐式实现。

现在问题是 FooFactory返回具体Foo对象,因为它们都在同一个 Foo 中包,不应该知道 Bar的本地定义的接口(interface)。但是,我想要 FooBuilder构建 Fooer 类型的对象而不是 Foo 类型的对象因为它不需要了解底层类型。 Go 不允许这样做,因为返回类型不同并且它说 FooFactory不实现FooBuilder .

这里是没有上述包结构的最小复制:

type Foo struct{}

func (f *Foo) FooMethod() {}

type FooFactory struct{}

func (ff *FooFactory) Build() *Foo {
return &Foo{}
}

type Fooer interface {
FooMethod()
}

type FooBuilder interface {
Build() Fooer
}

func main() {
f := &Foo{}
ff := &FooFactory{}

var fooer Fooer
var fooBuilder FooBuilder

fooer = f
fooBuilder = ff // << ERROR
}

去提示:

cannot use ff (type *FooFactory) as type FooBuilder in assignment:
*FooFactory does not implement FooBuilder (wrong type for Build method)
have Build() *Foo
want Build() Fooer

我的问题本质上是,我这样做吗?在拥有专业 C++ 和 Java 背景之后,我试图接受 Go 的隐式接口(interface)满足的概念,但这感觉很奇怪。事实上,这并不容易做到,让我觉得我做错了什么,但我在网上读到的有关 go 接口(interface)的所有内容都说要在靠近使用位置的地方定义接口(interface),这才是我真正想做的.

最佳答案

概念上

你的方法是正确的。不过,如果 Foo 的设置并不复杂,我会放弃工厂。

FooFooer 可能位于也可能不位于不同的包中。我首先将它们放在同一个包中,直到它不再有意义为止。

我通常设置这些情况的方式是:

package foo

func NewFoo() *Foo {
return &Foo{}
}

type Foo struct{}

func (f *Foo) FooMethod() {}

type Fooer interface {
FooMethod()
}

消费者:

package bar

func FooUser(f Fooer) {
//Do something
}

并将其与以下内容放在一起:

package main

import (
"foo"
"bar"
)

func main() {
f := foo.NewFoo()
bar.FooUser(f)
}

这样您就可以将 foo 包作为一个单元进行测试,并使用任何实现 Fooer 的结构来测试 bar 包。

您会发现很多核心包也是以这种方式构建的。

编译器错误

您缺少的一点是 FooFactory 实际上并未实现 FooBuilder 接口(interface)。

FooBuilder 接口(interface)声明了一个返回 Fooer 的方法,但 FooFactory 的方法签名返回一个指向 Foo 的指针。

func (ff *FooFactory) Build() *Foo

因此,您声明了方法 Build 但返回了错误的类型,因此它不会被识别为实现。

要修复该错误,请将 Build 实现的签名更改为:

func (ff *FooFactory) Build() Fooer

关于go - 使用工厂模式时接口(interface)应该在哪里定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58536878/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com