行为型:一. 观察者模式

观察者模式是什么

观察者模式是一种行为设计模式, 允许一个对象将其状态的改变通知其他对象。观察者模式允许你定义一种订阅机制, 可在对象事件发生时通知多个观察者。

为什么用观察者模式

当一个对象状态改变时需要改变其他对象,可使用观察者模式。它定义对象间的一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。

观察者模式怎么实现

subject.go是主体,sbserver.go是观察者。当item的对象发生变化的时候就会通知多个customer观察者。

subject.go

package observer

import "fmt"

type subject interface {
    register(Observer observer)
    deregister(Observer observer)
    notifyAll()
}

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 observer

import "fmt"

type observer interface {
    update(string)
    getID() string
}

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
}

客户端调用

func Example() {

    shirtItem := newItem("Nike Shirt")

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

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

    shirtItem.updateAvailability()
}

优点

  1. 开闭原则。 你无需修改发布者代码就能引入新的订阅者类 (如果是发布者接口则可轻松引入发布者类)。
  2. 你可以在运行时建立对象之间的联系
  3. 观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。

缺点

  1. 订阅者的通知顺序是随机的。
posted @ 2022-04-11 21:11  EthanWell  阅读(101)  评论(0编辑  收藏  举报