GoLang设计模式14 - 观察者模式(行为型)
观察者模式是一种行为型设计模式。这种模式允许一个实例(可以称为目标对象)发布各种事件(event)给其他实例(观察者)。这些观察者会对目标对象进行订阅,这样每当目标对象发生变化时,观察者就会收到事件(event)通知。
来看个例子:在电商网站经常会有各种商品脱销,假如有顾客已经在关注这些商品,这些商品的脱销就会对他们产生不好的体验。如果顾客还想买这些商品,那么通常有如下解决方案:
- 顾客以一定的频率检查这些商品是否在售
- 电商平台将所有的上架的商品信息定期推送给用户
- 顾客只订阅他所关注的特定商品的信息,当这些商品再次上架时他们会收到通知;多个顾客可以订阅同一个商品的信息
选项3是最为可行的一种方案。这也正是观察者模式所能做到的事情。观察者模式的核心组件为:
- Subject : 目标对象,是有变化发生时就会发布相关事件的实例
- Observer : 观察者,订阅目标对象的信息,会收到一些特定事件的通知
通常,Subject和Observer会被定义为接口,真正使用的是它们二者的具体实现。
UML类图如下:

下面是一个示例代码:
1 type observer interface { 2 update(string) 3 getID() string 4 } 5 type subject interface { 6 register(Observer observer) 7 deregister(Observer observer) 8 notifyAll() 9 } 10 type item struct { 11 observerList []observer 12 name string 13 inStock bool 14 } 15 16 func newItem(name string) *item { 17 return &item{ 18 name: name, 19 } 20 } 21 22 func (i *item) updateAvailability() { 23 fmt.Printf("Item %s is now in stock\n", i.name) 24 i.inStock = true 25 i.notifyAll() 26 } 27 28 func (i *item) register(o observer) { 29 i.observerList = append(i.observerList, o) 30 } 31 32 func (i *item) deregister(o observer) { 33 i.observerList = removeFromSlice(i.observerList, o) 34 } 35 36 func (i *item) notifyAll() { 37 for _, observer := range i.observerList { 38 observer.update(i.name) 39 } 40 } 41 42 func removeFromSlice(observerList []observer, observerToRemove observer) []observer { 43 observerListLength := len(observerList) 44 for i, observer := range observerList { 45 if observerToRemove.getID() == observer.getID() { 46 observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1] 47 return observerList[:observerListLength-1] 48 } 49 } 50 return observerList 51 } 52 type customer struct { 53 id string 54 } 55 56 func (c *customer) update(itemName string) { 57 fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName) 58 } 59 60 func (c *customer) getID() string { 61 return c.id 62 }
在上面的代码中item是subject的实现,customer是observer实现。
看下场景类main.go:
1 func main() { 2 shirtItem := newItem("GoLang Design Patterns") 3 observerFirst := &customer{id: "robin@zhyea.com"} 4 observerSecond := &customer{id: "golang@zhyea.com"} 5 shirtItem.register(observerFirst) 6 shirtItem.register(observerSecond) 7 shirtItem.updateAvailability() 8 }
执行后输出内容为:
1 Item GoLang Design Patterns is now in stock 2 Sending email to customer robin@zhyea.com for item GoLang Design Patterns 3 Sending email to customer golang@zhyea.com for item GoLang Design Patterns
浙公网安备 33010602011771号