Go 观察者形式解说和代码示例

观察者是一种行为规划形式, 允许一个目标将其状态的改动告诉其他目标

观察者形式供给了一种作用于任何实现了订阅者接口的目标的机制, 可对其事情进行订阅和撤销订阅。

概念示例

电商网站中, 产品时不时地会出现缺货情况。 可能会有客户关于缺货的特定产品表现出爱好。 这一问题有三种解决方案:

  1. 客户以必定的频率查看产品的可用性
  2. 电商网站向客户发送有库存的一切新产品。
  3. 客户只订阅其感爱好的特定产品, 产品可用时便会收到告诉。 一起, 多名客户也可订阅同一款产品。

选项 3 是最具可行性的, 这其实便是观察者形式的思维。 观察者形式的主要组成部分有:

  • 会在有任何事产生时发布事情的主体。
  • 订阅了主体事情并会在事情产生时收到告诉的观察者。

subject.go: 主体

package main
type Subject interface {
	register(observer Observer)
	deregister(obs Observer)
	notifyAll()
}

item.go: 详细主体

package main
import (
	"fmt"
)
type Item struct {
	observerList []Observer // 多个观察者
	name         string
	inStock      bool // 有库存
}
func newItem(name string) *Item {
	return &Item{
		name:    name,
		inStock: false,
	}
}
// 更新状态
func (i *Item) updateAvailability() {
	fmt.Printf("Item %s is now in stock \n", i.name)
	i.inStock = true // 更新状态,有库存 s
	i.notifyAll()
}
func (i *Item) register(o Observer) {
	i.observerList = append(i.observerList, o)
}
func (i *Item) deregister(o Observer) {
	i.observerList = removeFromslice(i.observerList, o)
}
func (i *Item) notifyAll() {
	for _, v := range i.observerList {
		v.update(i.name)
	}
}
func removeFromslice(observerList []Observer, observerToRemove Observer) []Observer {
	observerListLength := len(observerList)
	for i, observer := range observerList {
		if observerToRemove.getID() == observer.getID() {
			observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
			return observerList[:observerListLength-1]
		}
	}
	return observerList
}

observer.go: 观察者

package main
type Observer interface {
	update(string)
	getID() string
}

customer.go: 详细观察者

package main
import "fmt"
type Customer struct {
	id string
}
func (c *Customer) getID() string {
	return c.id
}
func (c *Customer) update(iteName string) {
	fmt.Printf("Sendint email to customer %s for item %s\n", c.id, iteName)
}

main.go: 客户端代码

package main
func main() {
	shirtItem := newItem("Nick Shirt")
	observerFirst := &Customer{
		id: "abc@gmail.com",
	}
	observerSecond := &Customer{
		id: "def@gmail.com",
	}
	shirtItem.register(observerFirst)
	shirtItem.register(observerSecond)
	shirtItem.updateAvailability()
}

output.txt: 履行结果

Item Nick Shirt is now in stock
Sendint email to customer abc@gmail.com for item Nick Shirt
Sendint email to customer def@gmail.com for item Nick Shirt