【Go-设计模式】观察者模式 详解

shadowLogo

概念:

观察者模式 用于 触发联动
一个对象的改变 会触发 其它观察者的相关动作,而 此对象 无需关心 联动对象具体实现

对象之间 多对一依赖 的一种设计方案,被依赖的对象Subject依赖的对象ObserverSubject 通知 Observer 变化

weather


UML:

uml

  • Subject
    抽象主题角色,把所有对 观察者对象的引用 保存在一个 集合 中。
    抽象主题 提供一个 接口,可以 增加删除 观察者对象,
    抽象主题角色 又叫做 抽象被观察者(Observable)角色
  • ConcreteSubject
    有关状态 存入 具体观察者对象
    在具体主题的 内部状态 改变 时,给 所有登记过 的 观察者 发出通知
    具体主题角色 又叫做 具体被观察者(Concrete Observable)角色
  • Observer
    所有的具体观察者 定义一个 接口,在 得到主题的通知触发动作
  • ConcreteObserver
    存储 与 主题的状态 符合 的状态
    具体观察者角色 实现 抽象观察者角色 所要求的 触发动作具体实现

示例:

被观察者 功能接口:

type Subject interface {
	RegisterObserver(observer Observer)
	RemoveObserver(observer Observer)
	NotifyObservers(message string)
}

被观察者 具体实现:

type ConcreteSubject struct {
	message     string
	observerSet map[Observer]struct{}
}

func (this *ConcreteSubject) RegisterObserver(observer Observer) {
	this.observerSet[observer] = struct{}{}
}

func (this *ConcreteSubject) RemoveObserver(observer Observer) {
	delete(this.observerSet, observer)
}

func (this *ConcreteSubject) NotifyObservers(message string) {
	for observer := range this.observerSet {
		notifyMessage := fmt.Sprintf("【ConcreteSubject】message: %v", message)
		observer.Update(notifyMessage)
	}
}

func NewConcreteSubject() ConcreteSubject {
	return ConcreteSubject{
		observerSet: map[Observer]struct{}{},
	}
}

观察者 功能接口:

type Observer interface {
	Update(message string)
}

观察者 具体实现:

具体实现1:

type ConcreteObserver1 struct {
	message string
}

func (this *ConcreteObserver1) Update(message string) {
	this.message = message
	this.display()
}

func (this *ConcreteObserver1) display() {
	recievedMessage := fmt.Sprintf("*** 具体观察者1,收到的信息为:%v ***", this.message)
	fmt.Println(recievedMessage)
}

具体实现2:

type ConcreteObserver2 struct {
	message string
}

func (this *ConcreteObserver2) Update(message string) {
	this.message = message
	this.display()
}

func (this *ConcreteObserver2) display() {
	recievedMessage := fmt.Sprintf("*** 具体观察者2,收到的信息为:%v ***", this.message)
	fmt.Println(recievedMessage)
}

测试:

package main

import (
	"DemoProject/design/base23/observer"	// 根据自己的项目路径定制
	"fmt"
)

func main() {
	// observer
	subject := observer.NewConcreteSubject()

	observer1 := observer.ConcreteObserver1{}
	observer2 := observer.ConcreteObserver2{}

	fmt.Println("============ register observe ============")
	subject.RegisterObserver(&observer1)
	subject.RegisterObserver(&observer2)
	subject.NotifyObservers("Youzg is a good man!")

	fmt.Println("============ remove observe ============")
	subject.RemoveObserver(&observer1)
	subject.NotifyObservers("And Youzg is so cool!")
}


注意事项:

观察者模式中,会以 集合 的方式来 管理 观察者(Observer),包括 注册移除通知

增加观察者 不需要去 修改核心类 ConcreteSubject, 遵守了 ocp(开闭原则)原则

posted @ 2021-12-14 08:59  在下右转,有何贵干  阅读(83)  评论(0)    收藏  举报