设计模式之观察者模式

miloyang
0 评论
/ /
528 阅读
/
3466 字
23 2023-11

简介

观察者模式(Observer Pattern)是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。

观察者模式中有两个主要角色:主题(Subject)和观察者(Observer)。

jugelizi

现在的汽车都带有手机app,一旦车子状态有问题,就会通知手机,同时汽车中控显示屏也会显示。这样显示屏和手机都同时监听着比如胎压、机油等等,一旦有问题,所有的观察者都会收到通知。

Demo

// CarObserver 观察者接口
type CarObserver interface {
    breakdown(level int, info string)
}

// CarInfoCenter 主题接口
type CarInfoCenter interface {
    RegisterObserver(observer CarObserver)
    RemoveObserver(observer CarObserver)
    NotifyObservers()
    SetCarStatus(level int, info string)
}

// CarInfoCenterImpl 具体主题
type CarInfoCenterImpl struct {
    observers []CarObserver
    mutex     sync.Mutex
    info      string
    level     int
}

func (cic *CarInfoCenterImpl) RegisterObserver(observer CarObserver) {
    cic.mutex.Lock()
    defer cic.mutex.Unlock()
    cic.observers = append(cic.observers, observer)
}
func (cic *CarInfoCenterImpl) RemoveObserver(observer CarObserver) {
    cic.mutex.Lock()
    defer cic.mutex.Unlock()
    for i, carObserver := range cic.observers {
        if carObserver == observer {
            cic.observers = append(cic.observers[:i], cic.observers[i+1:]...)
            break
        }
    }
}

func (cic *CarInfoCenterImpl) NotifyObservers() {
    cic.mutex.Lock()
    defer cic.mutex.Unlock()
    for _, observer := range cic.observers {
        observer.breakdown(cic.level, cic.info)
    }
}

func (cic *CarInfoCenterImpl) SetCarStatus(level int, info string) {
    cic.info = info
    cic.level = level
    cic.NotifyObservers()
}

type CarDisplay struct {
}

func (c *CarDisplay) breakdown(level int, info string) {
    fmt.Println("car display receive breakdown level:", level, " , info:", info)
}

type AppDisplay struct {
}

func (a *AppDisplay) breakdown(level int, info string) {
    fmt.Println("app display receive breakdown level:", level, " , info:", info)
}

test

func TestObserver(t *testing.T) {

    // 创建具体主题
    carInfoCenter := &CarInfoCenterImpl{}

    // 创建具体观察者
    carDisplay := &CarDisplay{}
    appDisplay := &AppDisplay{}

    // 注册观察者
    carInfoCenter.RegisterObserver(carDisplay)
    carInfoCenter.RegisterObserver(appDisplay)

    carInfoCenter.SetCarStatus(1, "胎压低,报警") // carDisplay和appDisplay都会收到通知

    carInfoCenter.RemoveObserver(appDisplay) // 移除app监听

    carInfoCenter.SetCarStatus(2, "燃油不足") // 只有carDisplay收到通知
}

在这个例子中,CarInfoCenter 是主题接口,定义了注册、移除和通知观察者的方法。CarObserver 是观察者接口,定义了接收更新通知的方法。CarInfoCenterImpl 是具体主题,实现了主题接口,并在车辆状态变化时通知注册的观察者。CarDisplay 和 AppDisplay 是具体观察者,实现了观察者接口,它们在接收到更新通知时输出相应的信息。

在 main 函数中,我们创建了具体主题 carInfoCenter 和两个具体观察者 carDisplay 和 AppDisplay,然后注册观察者并设置汽车状态,观察者收到相应的更新通知。之后,移除一个观察者并再次设置汽车状态,剩下的观察者继续收到通知。

通过这个例子,可以清晰地看到观察者模式的应用,其中汽车信息中心是主题,app显示器和汽车显示器是观察者,它们之间建立了一种松耦合的关系,实现了状态的动态更新。

作用和场景

  • 解耦

    观察者模式能够实现发布者和订阅者之间的解耦,使得它们可以独立变化。

  • 动态更新

    当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新,实现动态更新。

  • 事件驱动

    观察者模式常用于事件驱动系统,其中一个对象的状态变化触发一系列事件,通知所有观察者进行相应处理。

  • 分布式事件处理系统

    在分布式系统中,观察者模式可以用于构建事件处理系统,实现对象之间的通信和协同工作。

总体而言,观察者模式适用于需要实现发布-订阅机制、解耦发布者和订阅者、动态更新等场景。通过观察者模式,可以建立一种松耦合的关系,使得对象之间更加灵活、可扩展和易维护。

人未眠
工作数十年
脚步未曾歇,学习未曾停
乍回首
路程虽丰富,知识未记录
   借此博客,与之共进步