• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

Go基于观察者模式实现的订阅/发布

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

面UCloud的时候问到了这题,下来看了一下是基于观察者模式实现的,仅作记录

/**
 * @Author: lzw5399
 * @Date: 2021/5/20 20:38
 * @Desc: 基于观察者模式实现的订阅发布
 */
package main

import (
	"errors"
	"fmt"
	"sync"
)

func main() {
	server := NewServer()
	server.Subscribe("CCTV1", NewBasicClient("张三"))
	server.Subscribe("CCTV2", NewBasicClient("张三"))
	server.Subscribe("CCTV1", NewBasicClient("李四"))

	server.Publish("CCTV1", "开播辣!")
}

// ---server---
type Server struct {
	Topics map[string]*Topic  // k=topicName v=topic
	sync.RWMutex
}

func NewServer() *Server {
	return &Server{
		Topics:  make(map[string]*Topic),
		RWMutex: sync.RWMutex{},
	}
}

func (s *Server) Subscribe(topicName string, client Client) {
	s.RLock()
	topic, exist := s.Topics[topicName]
	s.RUnlock()

	// 存在topic直接添加client
	if exist {
		topic.AddClient(client)
		return
	}

	// 不存在topic,新建topic,在添加client
	topic = NewTopic(topicName)
	topic.AddClient(client)
	s.Lock()
	s.Topics[topicName] = topic
	s.Unlock()
}

func (s *Server) Publish(topicName string, message string) error {
	s.RLock()
	topic, exist := s.Topics[topicName]
	s.RUnlock()

	if exist {
		topic.Notify(message)
		return nil
	}

	return errors.New("当前topic不存在")
}

// ---end server---

// ---topic---
type Topic struct {
	Name    string
	clients map[string]Client  // k=clientName v=client
	sync.RWMutex
}

func NewTopic(name string) *Topic {
	return &Topic{
		Name:    name,
		clients: make(map[string]Client),
		RWMutex: sync.RWMutex{},
	}
}

func (t *Topic) AddClient(client Client) {
	// 只添加存在的
	if _, exist := t.clients[client.Name()]; !exist {
		t.Lock()
		t.clients[client.Name()] = client
		t.Unlock()
	}
}

func (t *Topic) Notify(message string) {
	for _, v := range t.clients {
		v.ConsumeCallback(message)
	}
}

// ---end topic---

// ---client---
type Client interface {
	Name() string
	ConsumeCallback(message string)
}

type BasicClient struct {
	name string
}

func NewBasicClient(name string) *BasicClient {
	return &BasicClient{
		name: name,
	}
}

func (b *BasicClient) Name() string {
	return b.name
}

func (b *BasicClient) ConsumeCallback(message string) {
	fmt.Printf("当前Client: %s, 接收到的消息为: %s\n", b.Name(), message)
}

// ---end client---

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
设计模式学习-使用go实现单例模式发布时间:2022-07-10
下一篇:
二十二、Go基础编程:并发编程—channel发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap