《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)

相关推荐
apocelipes2 小时前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
槑有老呆3 小时前
从 Prompt Engineering 到 Harness Engineering:AI 编程的下一次跃迁
设计模式
HjhIron12 小时前
从Prompt到Context:大模型应用开发的范式转移
设计模式·aigc·ai编程
咖啡八杯2 天前
GoF设计模式——中介者模式
java·后端·spring·设计模式
胡萝卜术2 天前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
亦暖筑序3 天前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
青禾网络6 天前
Web 前端如何接入 AI 音效生成:从零到可用的完整方案
人工智能·设计模式
ZJPRENO6 天前
吃透软件开发六大设计原则,告别烂代码
设计模式
咖啡八杯7 天前
GoF设计模式——命令模式
java·设计模式·架构
花椒技术7 天前
HJPusher / HJPlayer SDK 实践:我们为什么把直播推播链路拆成一套可复用能力
设计模式·harmonyos·直播