GoLang设计模式14 - 观察者模式(行为型)

观察者模式是一种行为型设计模式。这种模式允许一个实例(可以称为目标对象)发布各种事件(event)给其他实例(观察者)。这些观察者会对目标对象进行订阅,这样每当目标对象发生变化时,观察者就会收到事件(event)通知。

来看个例子:在电商网站经常会有各种商品脱销,假如有顾客已经在关注这些商品,这些商品的脱销就会对他们产生不好的体验。如果顾客还想买这些商品,那么通常有如下解决方案:

  1. 顾客以一定的频率检查这些商品是否在售
  2. 电商平台将所有的上架的商品信息定期推送给用户
  3. 顾客只订阅他所关注的特定商品的信息,当这些商品再次上架时他们会收到通知;多个顾客可以订阅同一个商品的信息

选项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

 

posted @ 2023-04-21 11:37  格局打得开  阅读(67)  评论(0)    收藏  举报