《golang设计模式》第三部分·行为型模式-07-观察者模式(Observer)/发布者—订阅者模式

文章目录

  • [1. 概念](#1. 概念)
    • [1.1 角色](#1.1 角色)
    • [1.2 类图](#1.2 类图)
  • [2. 代码示例](#2. 代码示例)
    • [2.1 代码](#2.1 代码)
    • [2.2 类图](#2.2 类图)

1. 概念

观察者(Observer)指当目标对象状态发生变化后,对状态变化事件进行响应或处理的对象。

1.1 角色

  • Subject(抽象主题):
    • 它可以有多个观察者,并将所有观察者对象的引用保存在一个集合里
    • 被观察者提供一个接口,可以增加和删除观察者角色
  • ConcreteSubject(具体主题):
    • 将有关状态存入具体观察者对象
    • 在主题发生改变时,给所有的观察者发出通知
  • Observer(抽象观察者):
    • 为所有的具体观察者定义一个更新接口,在收到主题的通知时能够及时的更新自己
  • ConcreteObserver(具体观察者):
    • 实现抽象观察者角色定义的更新接口,以便使本身的状态与主题状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。

1.2 类图

Subject -observer:List +Add(o:Observer) +NotifyObserver() +ChangeState() ConcreteSubject +ChangeState() <<interface>> Observer +Update(s:State) ConcreteObserverA +Update(s:State) ConcreteObserverB +Update(s:State)

2. 代码示例

2.1 代码

  • 代码
go 复制代码
package main

import "fmt"

//定义抽象主题,它是观察者的聚合
type Subject struct{  
   observers []Observer
}

//定义一个方法,为抽象主题添加观察者
func (c *Subject) Attach(o ...Observer) {
   c.observers = append(c.observers, o...)
}


//定义实际主题,继承抽象主题,它是实际的被观察者。
type ConcreteSubject struct {
   Subject    Subject
   context   string
  }

  
//依次通知观察者
func (c *ConcreteSubject) notify() {
   for _, o := range c.Subject.observers {
    o.Update(c)
   }
 }
 
//具体抽象主题的,同时发送通知给观察者
func (c *ConcreteSubject) UpdateContext(context string) {
   c.context = context
   c.notify()
}
  
//定义抽象观察者
type Observer interface {
   Update(*ConcreteSubject)
}
  
//定义具体观察者
type ConcreteObserverA struct {
   name string
}

//更新观察者
func (r *ConcreteObserverA) Update(c *ConcreteSubject) {
   fmt.Printf("%s receive %q\n", r.name, c.context)
} 
  
//定义具体观察者
type ConcreteObserverB struct {
   name string
}

//更新观察者
func (r *ConcreteObserverB) Update(c *ConcreteSubject) {
   fmt.Printf("%s receive %q\n", r.name, c.context)
} 

//定义具体观察者
type ConcreteObserverC struct {
   name string
}

//更新观察者
func (r *ConcreteObserverC) Update(c *ConcreteSubject) {
   fmt.Printf("%s receive %q\n", r.name, c.context)
} 

func main() {
   //实例化抽象主题
   subject := Subject{
      observers: make([]Observer, 0),
   }
 
   //实例化3观察者
   concreteObserverA := &ConcreteObserverA{
      name: "concreteObserverA",
     }
     concreteObserverB := &ConcreteObserverB{
      name: "concreteObserverB",
     }
     concreteObserverC := &ConcreteObserverC{
      name: "concreteObserverC",
     }
   //将3个观察者加入抽象主题
   subject.Attach(concreteObserverA,concreteObserverB,concreteObserverC)

   //实例化具体主题
   concreteSubject := &ConcreteSubject{
      Subject: subject,
   }

   //更新具体主题,它将通知所有观察者
   concreteSubject.UpdateContext("updata context")
}
  • 输出
shell 复制代码
concreteObserverA receive "updata context"
concreteObserverB receive "updata context"
concreteObserverC receive "updata context"

2.2 类图

Subject +\[\]Observe observers +Attach(o ...Observer) ConcreteSubject +Subject:Subject +context:String +Notify() +UpdateContext(context string) <<interface>> Observer +Update(c *ConcreteSubject) ConcreteObserverA +Name:String +Update(c *ConcreteSubject) ConcreteObserverB +Name:String +Update(c *ConcreteSubject) ConcreteObserverC +Name:String +Update(c *ConcreteSubject)

相关推荐
ttwuai2 天前
Go开源后台管理系统推荐:怎么按技术栈和边界比较4个官方仓库?
golang·gin
codeejun2 天前
每日一Go·MySQL-5、锁机制全解析
云原生·golang
Achou.Wang2 天前
k8s中nginx worker process自动设置
后端·golang
Zane19942 天前
一个 new 就能创建对象,为什么还要拆出单例、工厂、建造者、原型四种模式?
设计模式
怕浪猫3 天前
一行命令复刻爆款视频,我把 Hypit 从安装跑到了出片
人工智能·设计模式·程序员
Zane19943 天前
函数式编程里的函数,其实不是你天天写的那个函数——三大编程范式的边界在哪
设计模式
指尖的爷3 天前
ARM 架构 Ubuntu(RK3588/aarch64)go开发环境安装手册
ubuntu·架构·golang
名字还没想好☜3 天前
Go 实现指数退避重试:context 取消、抖动 jitter 与什么时候别重试
后端·golang·go
Casbin开源社区3 天前
OpenAgent 详解:单二进制自托管 AI Agent 平台,30+ 模型接入、RAG 知识库、MCP 工具调用与 Casbin 工具权限
人工智能·golang·开源
五彩小白4 天前
GO语言装饰器语法
golang