在 Golang 中使用组合的正确方法是什么
What is the proper way using composition in Golang
我是 OOP 的家伙,最近我必须在 Golang 上工作,这是我以前没有做过的语言。虽然我已经看过很多关于组合的文章,但我注意到在 Golang 上正确使用它有点棘手
假设我有两个 Golang 组合的例子,我不知道哪一个是正确的,它们之间会有所不同吗?谢谢
第一个例子
type BaseClass struct {
db *DB
}
func NewBaseClass(db *DB) *BaseClass {
return &BaseClass{db}
}
type ChildrenClass1 struct {
baseClass *BaseClass
}
func NewChildrenClass1(db *DB) *ChildrenClass1 {
baseClass := NewBaseClass(db)
return &ChildrenClass1{baseClass}
}
type ChildrenClass2 struct {
baseClass *BaseClass
}
func NewChildrenClass2(db *DB) *ChildrenClass2 {
baseClass := NewBaseClass(db)
return &ChildrenClass2{baseClass}
}
func main(){
db := NewDB()
chilrend1 := NewChildrenClass1(db)
chilrend2 := NewChildrenClass2(db)
}
第二个例子
type BaseClass struct {
db *DB
}
func NewBaseClass(db *DB) *BaseClass {
return &BaseClass{db}
}
type ChildrenClass1 struct {
baseClass *BaseClass
}
func NewChildrenClass1(baseClass *BaseClass) *ChildrenClass1 {
return &ChildrenClass1{baseClass}
}
type ChildrenClass2 struct {
baseClass *BaseClass
}
func NewChildrenClass2(baseClass *BaseClass) *ChildrenClass2 {
return &ChildrenClass2{baseClass}
}
func main(){
db := NewDB()
baseClass := NewBaseClass(db)
chilrend1 := NewChildrenClass1(baseClass)
chilrend2 := NewChildrenClass2(baseClass)
}
在 Go 中,您可能找不到 正确的方法 来定义组合或聚合,而您可能会在许多其他基于 OOP 的语言中找到这种方法。这只是因为 Go has no classes,没有 object,没有异常,也没有模板。
但是 Go 有结构。结构是 user-defined 类型。结构类型(带有方法)的用途与其他语言中的 类 相似。
说到这里,让我们看看一些常见的定义,看看我们能做什么:
Composition 意味着 child 不能独立于 parent 而存在的关系。示例:房屋 (parent) 和房间 (child)。房间不独立于房屋[1]。
另一方面,聚合 表示 child 可以独立于 parent 存在的关系。示例:教室 (parent) 和学生 (child)。删除教室,学生仍然存在[1]。
因此,在 aggregation and composition 中,“实例”“拥有”另一种类型的 object。但有一个微妙的区别:聚合 意味着 child 可以独立于 parent 存在的关系。 组合 意味着 child 不能独立于 parent 存在的关系。
到目前为止,这就是我们从 composition:
中了解到的信息
- child 没有 parent
就不可能存在
- 组合是指将较简单的类型组合成更复杂的类型
- 当然,我们主要用它来重用代码
你问题的答案:
两者看起来都正确,但是,
- 第一个例子更接近组合,因为没有parent;
就不会有child
- 第二个示例更像是一个 聚合,因为如果您删除 parent,child 将保持存在。
我re-wrote你的代码试图举例说明它:
第一个例子re-written
package main
//Lamp struct is here to suppress the *DB that was in the original example
type Lamp struct {}
type Room struct {
Lamps *[]Lamp
}
func NewRoom(l *[]Lamp) *Room {
return &Room{l}
}
type House1 struct {
Room *Room
}
func NewHouse1(l *[]Lamp) *House1 {
r := NewRoom(l)
return &House1{r}
}
type House2 struct {
Room *Room
}
func NewHouse2(l *[]Lamp) *House2 {
r := NewRoom(l)
return &House2{r}
}
func main(){
lamps := []Lamp{}
house1 := NewHouse1(&lamps)
house2 := NewHouse2(&lamps)
}
第二个例子re-written:
package main
type LibraryCard struct {}
type Student struct {
LibCard *LibraryCard
}
func NewStudent(l *LibraryCard) *Student {
return &Student{l}
}
type Classroom1 struct {
Student *Student
}
func NewClassroom1(s *Student) *Classroom1 {
return &Classroom1{s}
}
type Classroom2 struct {
Student *Student
}
func NewClassroom2(s *Student) *Classroom2 {
return &Classroom2{s}
}
func main(){
lc := new(LibraryCard)
student := NewStudent(lc)
classroom1 := NewClassroom1(student)
classroom2 := NewClassroom2(student)
}
我是 OOP 的家伙,最近我必须在 Golang 上工作,这是我以前没有做过的语言。虽然我已经看过很多关于组合的文章,但我注意到在 Golang 上正确使用它有点棘手
假设我有两个 Golang 组合的例子,我不知道哪一个是正确的,它们之间会有所不同吗?谢谢
第一个例子
type BaseClass struct {
db *DB
}
func NewBaseClass(db *DB) *BaseClass {
return &BaseClass{db}
}
type ChildrenClass1 struct {
baseClass *BaseClass
}
func NewChildrenClass1(db *DB) *ChildrenClass1 {
baseClass := NewBaseClass(db)
return &ChildrenClass1{baseClass}
}
type ChildrenClass2 struct {
baseClass *BaseClass
}
func NewChildrenClass2(db *DB) *ChildrenClass2 {
baseClass := NewBaseClass(db)
return &ChildrenClass2{baseClass}
}
func main(){
db := NewDB()
chilrend1 := NewChildrenClass1(db)
chilrend2 := NewChildrenClass2(db)
}
第二个例子
type BaseClass struct {
db *DB
}
func NewBaseClass(db *DB) *BaseClass {
return &BaseClass{db}
}
type ChildrenClass1 struct {
baseClass *BaseClass
}
func NewChildrenClass1(baseClass *BaseClass) *ChildrenClass1 {
return &ChildrenClass1{baseClass}
}
type ChildrenClass2 struct {
baseClass *BaseClass
}
func NewChildrenClass2(baseClass *BaseClass) *ChildrenClass2 {
return &ChildrenClass2{baseClass}
}
func main(){
db := NewDB()
baseClass := NewBaseClass(db)
chilrend1 := NewChildrenClass1(baseClass)
chilrend2 := NewChildrenClass2(baseClass)
}
在 Go 中,您可能找不到 正确的方法 来定义组合或聚合,而您可能会在许多其他基于 OOP 的语言中找到这种方法。这只是因为 Go has no classes,没有 object,没有异常,也没有模板。
但是 Go 有结构。结构是 user-defined 类型。结构类型(带有方法)的用途与其他语言中的 类 相似。
说到这里,让我们看看一些常见的定义,看看我们能做什么:
Composition 意味着 child 不能独立于 parent 而存在的关系。示例:房屋 (parent) 和房间 (child)。房间不独立于房屋[1]。
另一方面,聚合 表示 child 可以独立于 parent 存在的关系。示例:教室 (parent) 和学生 (child)。删除教室,学生仍然存在[1]。
因此,在 aggregation and composition 中,“实例”“拥有”另一种类型的 object。但有一个微妙的区别:聚合 意味着 child 可以独立于 parent 存在的关系。 组合 意味着 child 不能独立于 parent 存在的关系。
到目前为止,这就是我们从 composition:
中了解到的信息- child 没有 parent 就不可能存在
- 组合是指将较简单的类型组合成更复杂的类型
- 当然,我们主要用它来重用代码
你问题的答案: 两者看起来都正确,但是,
- 第一个例子更接近组合,因为没有parent; 就不会有child
- 第二个示例更像是一个 聚合,因为如果您删除 parent,child 将保持存在。
我re-wrote你的代码试图举例说明它:
第一个例子re-written
package main
//Lamp struct is here to suppress the *DB that was in the original example
type Lamp struct {}
type Room struct {
Lamps *[]Lamp
}
func NewRoom(l *[]Lamp) *Room {
return &Room{l}
}
type House1 struct {
Room *Room
}
func NewHouse1(l *[]Lamp) *House1 {
r := NewRoom(l)
return &House1{r}
}
type House2 struct {
Room *Room
}
func NewHouse2(l *[]Lamp) *House2 {
r := NewRoom(l)
return &House2{r}
}
func main(){
lamps := []Lamp{}
house1 := NewHouse1(&lamps)
house2 := NewHouse2(&lamps)
}
第二个例子re-written:
package main
type LibraryCard struct {}
type Student struct {
LibCard *LibraryCard
}
func NewStudent(l *LibraryCard) *Student {
return &Student{l}
}
type Classroom1 struct {
Student *Student
}
func NewClassroom1(s *Student) *Classroom1 {
return &Classroom1{s}
}
type Classroom2 struct {
Student *Student
}
func NewClassroom2(s *Student) *Classroom2 {
return &Classroom2{s}
}
func main(){
lc := new(LibraryCard)
student := NewStudent(lc)
classroom1 := NewClassroom1(student)
classroom2 := NewClassroom2(student)
}