Autumn SALE
观察者

Go 观察者模式讲解和代码示例

观察者是一种行为设计模式 允许一个对象将其状态的改变通知其他对象

观察者模式提供了一种作用于任何实现了订阅者接口的对象的机制 可对其事件进行订阅和取消订阅

概念示例

在电商网站中 商品时不时地会出现缺货情况 可能会有客户对于缺货的特定商品表现出兴趣 这一问题有三种解决方案

  1. 客户以一定的频率查看商品的可用性
  2. 电商网站向客户发送有库存的所有新商品
  3. 客户只订阅其感兴趣的特定商品 商品可用时便会收到通知 同时 多名客户也可订阅同一款产品

选项 3 是最具可行性的 这其实就是观察者模式的思想 观察者模式的主要组成部分有

  • 会在有任何事发生时发布事件的主体
  • 订阅了主体事件并会在事件发生时收到通知的观察者

subject.go: 主体

package main

type Subject interface {
	register(observer Observer)
	deregister(observer 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,
	}
}
func (i *Item) updateAvailability() {
	fmt.Printf("Item %s is now in stock\n", i.name)
	i.inStock = true
	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 _, observer := range i.observerList {
		observer.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) update(itemName string) {
	fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}

func (c *Customer) getID() string {
	return c.id
}

main.go: 客户端代码

package main

func main() {

	shirtItem := newItem("Nike Shirt")

	observerFirst := &Customer{id: "abc@gmail.com"}
	observerSecond := &Customer{id: "xyz@gmail.com"}

	shirtItem.register(observerFirst)
	shirtItem.register(observerSecond)

	shirtItem.updateAvailability()
}

output.txt: 执行结果

Item Nike Shirt is now in stock
Sending email to customer abc@gmail.com for item Nike Shirt
Sending email to customer xyz@gmail.com for item Nike Shirt

观察者在其他编程语言中的实现

C# 观察者模式讲解和代码示例 C++ 观察者模式讲解和代码示例 Java 观察者模式讲解和代码示例 PHP 观察者模式讲解和代码示例 Python 观察者模式讲解和代码示例 Ruby 观察者模式讲解和代码示例 Rust 观察者模式讲解和代码示例 Swift 观察者模式讲解和代码示例 TypeScript 观察者模式讲解和代码示例