【设计模式】12、observer 观察者模式

文章目录

  • 十二、observer 观察者模式
    • 12.1 subscriber
      • 12.1.1 broker_test.go
      • 12.2.2 broker.go
      • 12.2.3 client.go

十二、observer 观察者模式

https://refactoringguru.cn/design-patterns/observer

发布订阅模式, client 都可以向 broker 注册, broker 管理所有 connection, 当 broker 收到某事件时, 广播给所有 clients.

  • 各种消息队列, 如 kafka, redis stream 都是这种结构
  • websocket server, live video streaming server 也都是这样的

12.1 subscriber

https://refactoringguru.cn/design-patterns/observer/go/example

如果有一个 websocket broker, 各种 client 都注册, 当 broker 收到消息时向各 clients 广播消息

12observer/121subscriber
├── broker.go
├── broker_test.go
├── client.go
└── readme.md

12.1.1 broker_test.go

package _21subscriber

import (
	"fmt"
	"testing"
)

/*
=== RUN   TestBroker
给ws连接通知
给ws连接通知
给http连接通知

给ws连接通知
给ws连接通知
给http连接通知
给tcp连接通知

给ws连接通知
给ws连接通知
给http连接通知
给tcp连接通知
--- PASS: TestBroker (0.00s)
PASS
*/
func TestBroker(t *testing.T) {
	b := NewBroker(&wsClient{}, &wsClient{}, &httpClient{})
	b.Broadcast()
	b.NotifySome("ws1", "ws2", "http3")
	fmt.Println()

	b.AddSubscription(&tcpClient{})
	b.Broadcast()
	fmt.Println()

	b.RemoveSubscription(&httpClient{})
	b.Broadcast()
}

12.2.2 broker.go

package _21subscriber

import (
	"slices"
)

type broker struct {
	clients []client
}

func NewBroker(clients ...client) *broker {
	return &broker{
		clients: clients,
	}
}

func (b *broker) AddSubscription(c client) {
	b.clients = append(b.clients, c)
}

func (b *broker) RemoveSubscription(c client) {
	clients := make([]client, 0)
	for _, cli := range b.clients {
		if c.ID() == cli.ID() {
			continue
		}
		clients = append(clients, cli)
	}
	b.clients = clients
}

func (b *broker) Broadcast() {
	for _, c := range b.clients {
		c.Notify()
	}
}

func (b *broker) NotifySome(ids ...string) {
	for _, c := range b.clients {
		if slices.Contains(ids, c.ID()) {
			c.Notify()
		}
	}
}

12.2.3 client.go

package _21subscriber

import (
	"fmt"
	"math/rand"
	"strconv"
)

type client interface {
	ID() string
	Notify()
}

type wsClient struct{}

func (c *wsClient) Notify() {
	fmt.Println("给ws连接通知")
}

func (c *wsClient) ID() string {
	return "ws" + strconv.Itoa(rand.Int())
}

type httpClient struct{}

func (c *httpClient) Notify() {
	fmt.Println("给http连接通知")
}

func (c *httpClient) ID() string {
	return "http" + strconv.Itoa(rand.Int())
}

type tcpClient struct{}

func (c *tcpClient) Notify() {
	fmt.Println("给tcp连接通知")
}

func (c *tcpClient) ID() string {
	return "tcp" + strconv.Itoa(rand.Int())
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/573763.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法-动态规划专题

文章目录 前言 : 动态规划简述1 . 斐波那契模型1.1 泰波那契数列1.2 最小花费爬楼梯1.3 解码方法 前言 : 动态规划简述 动态规划在当前我们的理解下,其实就是一种变相的递归,我们查看一些资料也可以知道,动态规划其实属于递归的一个分支,通过把递归问题开辟的栈帧通过一定的手…

模拟信号的离散化

本文介绍模拟信号的离散化。 1.采样定理 定义:若想重建输入的模拟信号,采样频率必须大于等于输入模拟信号最高频率的2倍,即: 其中,为采样频率,为输入模拟信号最高频率 否则,信号会发生混叠 2…

榕城·江上图三居装修攻略,硬装费用18万。福州中宅装饰,福州装修

设计亮点 **方案分析:** 整体墙面采用纯白色为主,搭配木质元素设计,室内铺设浅色木地板。客厅区域设计了一个嵌入式工作区,满足日常办公需求。餐厅、走廊和卧室充分利用每一处空间,扩大收纳空间。 **改造方案:** 1. 采用白色和原木…

Emby for Mac 1.9.9中文激活永久使用(多媒体影音库)

Emby 是一款流媒体服务器软件,可以用于在不同设备上共享音乐、电影、电视节目和照片等多媒体资源。用户可以将自己的媒体文件添加到Emby服务器中,并通过网络将它们发送到其他设备,如电视、手机、平板电脑等。 Emby for Mac 1.9.9中文激活下载…

Linux多进程(三) 信号信号集与统一事件源

信号是由用户、系统或者进程发送给目标进程的信息,以通知目标进程某个状态的改变或系统异常。Linux信号可由如下条件产生: 对于前台进程,用户可以通过输入特殊的终端字符来给它发送信号。比如输入CtrlC通常会给进程发送一个中断信号。系统异…

LeetCode:51. N 皇后

leetCode51.N皇后 题解分析 代码 class Solution { public:int n;vector<vector<string>> ans;vector<string> path;vector<bool> col, dg,udg;vector<vector<string>> solveNQueens(int _n) {n _n;col vector<bool> (n);dg …

如何在阿里云快速配置自动定时重启ECS云服务器?

背景 无论是电子商务、在线教育、游戏&#xff0c;还是流媒体等业务&#xff0c;服务器的稳定运行都是至关重要的。然而&#xff0c;在实际运行中&#xff0c;我们可能会遇到这样一些场景&#xff1a; 系统更新&#xff1a;一些操作系统或者软件的更新可能需要重启服务器才能…

政企版 WPS Pro 专业版注册安装教程

政企版 WPS Pro 专业版安装及激活步骤 第 1 步&#xff1a;下载压缩包&#xff08;内含注册码&#xff09;【无解压密码】。 第 2 步&#xff1a;解压缩后&#xff0c;运行 exe 文件&#xff0c;默认步骤安装即可。 第 3 步&#xff1a;安装完成后&#xff0c;新建一个 Word …

【Camera Sensor Driver笔记】五、点亮指南之Actuator配置

<slaveInfo> actuatorName dw9714v dirver IC 型号 slaveAddress 0x18 i2c write address i2cFrequencyMode FAST i2c 操作频率(400KHz) actuatorType VCM/BIVCM 马达类型 BIVCM&#xff08;中置马达&#xff…

Andorid进程间通信之 UNIX SOCKET

1&#xff0c;什么是UNIX SOCKET UNIX SOCKET&#xff0c;域套接字&#xff0c;UNIX SOCKET可用于同一台设备进程间通信&#xff0c;它不需要经过网络协议栈&#xff0c;不需要打包拆包、计算校验和、维护序列号应答等&#xff0c;只需要将数据从一个进程复制到另一个进程&…

WPS-EXCEL:快速删除多个线条对象

问题图 我需要将线条快速删除 方法一:使用定位对象功能 使用定位功能&#xff1a;按Ctrl G打开定位对话框。在对话框中&#xff0c;点击“定位条件”。 定位对象&#xff1a;在定位条件对话框中&#xff0c;勾选“对象”选项&#xff0c;然后点击“确定”。这样&#xff0c;…

git忽略文件配置 !

.gitignore中!表示取反 注意&#xff0c;如果父目录被排除&#xff0c;则父目录下的子目录也会被排除&#xff0c;此时对父目录下的子目录取反也不会生效&#xff0c;比如存在目录结构&#xff0c;再.gitignore目录下配置的 /*&#xff08;排除所有文件&#xff09;&#xff0c…

探索 Python 的动态类型系统:变量引用、不可变性及高效内存管理与垃圾回收机制的深入分析

文章目录 1. 动态类型及其内存管理解析1.1 变量与对象的引用关系1.2 对象的不可变性和内存地址的变化 2. 垃圾回收与内存优化策略2.1 动态内存分配的基础2.2 Python 的垃圾回收 Python作为一种流行的高级编程语言&#xff0c;以其代码的易读性和简洁性著称。尤其是它的动态类型…

U盘无法正常格式化?教你一个强力的办法

前言 电脑格式化U盘或者移动硬盘的操作&#xff0c;相信各位小伙伴都是有一定经历的。 如果设备正常&#xff0c;那么进入到【此电脑】&#xff0c;在对应的分区点击【鼠标右键】-【格式化】就可以把对应的存储设备恢复到初始状态。 但凡事都会有例外&#xff0c;比如在格式化…

SKF 与KISSSOFT的连接

SKF 与KISSSOFT的连接 HEDZER TILLEMA&#xff0c;荷兰SKF B.V.产品线经理 最近&#xff08;2019年&#xff09;&#xff0c;瑞典滚动轴承制造商斯凯孚&#xff08;SKF&#xff09;和瑞士齿轮箱设计软件开发商KISSsoft已将斯凯孚的轴承计算服务整合到KISSsoft的软件中。借助 K…

分布式技术在文本摘要生成中的应用

摘要 自然语言处理首先要应对的是如何表示文本以供机器处理&#xff0c;随着网络技术的发展和信息的公开&#xff0c;因特网上可供访问的数字文档成爆炸式的增长&#xff0c;文本摘要生成逐渐成为了自然语言处理领域的重要研究课题。本文主要介绍了分布式技术在文本摘要生成中…

软件工程中的耦合和内聚

耦合 在软件工程中&#xff0c;耦合是一个重要的概念&#xff0c;用于描述模块或组件之间的相互依赖程度。 从非直接耦合到内容耦合的耦合性依次升高&#xff0c;所以非直接耦合是我们最想见到的结果&#xff0c;内容耦合是我们最不想见到的结果。 非直接耦合数据耦合标记耦…

开源数据集分享———猫脸码客

猫脸码客作为一个专注于开源数据集分享的公众号&#xff0c;致力于为广大用户提供丰富、优质的数据资源。我们精心筛选和整理各类开源数据集&#xff0c;涵盖机器学习、深度学习、自然语言处理等多个领域&#xff0c;以满足不同用户的需求。 (https://img-blog.csdnimg.cn/d98…

【Python数据库】Redis

文章目录 [toc]数据插入数据查询数据更新数据删除查询存在的所有key 个人主页&#xff1a;丷从心 系列专栏&#xff1a;Python数据库 学习指南&#xff1a;Python学习指南 数据插入 from redis import Redisdef insert_data():redis_cli Redis(hostlocalhost, port6379, db…

【Java--数据结构】链表经典OJ题详解(上)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 谈谈头插、头删、尾插、头插的时间复杂度 反转一个单链表 链表的中间结点 返回倒数第k个结点 合并两个链表 谈谈头插、头删、尾插、头插的时间复杂度 头插和头删的时…