go - Go方式实现观察者设计模式

标签 go design-patterns observer-pattern

我的经验是使用 OOP 语言,但我已经开始尝试使用 Go。我无法找到实现 Observer design pattern 的最佳方法在围棋中。

我按如下方式组织了我的项目,其中 observers 文件夹中的所有内容都是 package observers 的一部分,而 subjects 文件夹中的所有内容都是包主题的一部分。将观察者附加到主题是在 main.go 中完成的。

my-project/
  main.go
  observers/
    observer.go
    observer_one.go
    observer_two.go
  subjects/
    subject.go
    subject_one.go

我看过 this section in the Go wiki关于接口(interface):

Go interfaces generally belong in the package that uses values of the interface type, not the package that implements those values. The implementing package should return concrete (usually pointer or struct) types: that way, new methods can be added to implementations without requiring extensive refactoring.

牢记来自 Go Wiki 的评论。我是这样实现的(省略了函数实现):

主题.go:

type ObserverInterface interface {
    Update(subject *Subject, updateType string)
}

type Subject struct {
    observers map[string][]ObserverInterface
}

func (s *Subject) Attach(observer ObserverInterface, updateType string) {}

func (s *Subject) Detach(observer ObserverInterface, updateType string) {}

func (s *Subject) notify(updateType string) {}

观察者.go:

type SubjectInterface interface {
   Attach(observer Observer, updateType string)
   Detach(observer Observer, updateType string)
   notify(updateType string)
}

type Observer struct {
    uuid uuid.UUID
}

observer_one.go

type ObserverOne struct {
    Observer
}

func (o *ObserverOne) Update(subject *SubjectInterface, updateType string) {}

主.go

subjectOne := &SubjectOne{}
observerOne := &ObserverOne{Observer{uuid: uuid.New()}}
subjectOne.Attach(observerOne, "update_type")

我希望能够使用 SubjectInterface 作为 ObserverOneUpdate() 方法的参数,这样我就可以避免依赖在我的 subject 包和我的 observer 包之间,但出现以下编译时错误。

observers/observer_one.go:29:35: cannot use &observer (type *ObserverOne) as type subjects.ObserverInterface in argument to SubjectOne.Subject.Attach:
    *ObserverOne does not implement subjects.ObserverInterface (wrong type for Update method)
        have Update(*SubjectInterface, string)
        want Update(*subjects.Subject, string)

如果我将 observer_one.go 中 Update() 的定义替换为以下内容,它可以正常编译,但我认为我的想法是使用接口(interface)来解耦包:

func (o *ObserverOne) Update(subject *subjects.Subject, updateType string) {}

最佳答案

首先,不要使用指向接口(interface)的指针。

func (o *ObserverOne) Update(subject *SubjectInterface, updateType string) {}

应该是

func (o *ObserverOne) Update(subject SubjectInterface, updateType string) {}

其次,您已将接口(interface)定义为需要具体类型:

type ObserverInterface interface {
    Update(subject *Subject, updateType string)
}

相反,让它接受一个接口(interface):

type ObserverInterface interface {
    Update(subject SubjectInterface, updateType string)
}

关于go - Go方式实现观察者设计模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57027133/

相关文章:

go - 为什么函数 runtime_args 可以这样表达?

security - 相当于 Golang 的 mysql_real_escape_string

json - 为什么 json.Marshal 似乎生成了一个整数数组?

design-patterns - 软件设计 : rotate between process modes

Java替代观察者模式

observer-pattern - 公告与经典 Smalltalk-80 依赖/更改/更新机制有何关系?

go - 当 channel 关闭时,以接收 channel 作为参数的 goroutines 是否停止?

design-patterns - IoC 服务的抽象类或接口(interface)?

swift - 使用其他类实例从类创建实例

java - MVC 井字游戏