GoLang设计模式13 - 观察者模式
观察者模式是一种行为型设计模式。这种模式允许一个实例(可以称为目标对象)发布各种事件(event)给其他实例(观察者)。这些观察者会对目标对象进行订阅,这样每当目标对象发生变化时,观察者就会收到事件(event)通知。
来看个例子:在电商网站经常会有各种商品脱销,假如有顾客已经在关注这些商品,这些商品的脱销就会对他们产生不好的体验。如果顾客还想买这些商品,那么通常有如下解决方案:
- 顾客以一定的频率检查这些商品是否在售
- 电商平台将所有的上架的商品信息定期推送给用户
- 顾客只订阅他所关注的特定商品的信息,当这些商品再次上架时他们会收到通知;多个顾客可以订阅同一个商品的信息
选项3是最为可行的一种方案。这也正是观察者模式所能做到的事情。观察者模式的核心组件为:
- Subject : 目标对象,是有变化发生时就会发布相关事件的实例
- Observer : 观察者,订阅目标对象的信息,会收到一些特定事件的通知
通常,Subject和Observer会被定义为接口,真正使用的是它们二者的具体实现。
UML类图如下:

下面是一个示例代码:
observer.go:
type observer interface {
update(string)
getID() string
}
subject.go:
type subject interface {
register(Observer observer)
deregister(Observer observer)
notifyAll()
}
item.go:
import "fmt"
type item struct {
observerList []observer
name string
inStock bool
}
func newItem(name string) *item {
return &item{
name: name,
}
}
func (i *item) updateAvailability() {
fmt.Printf("Item %s is now in stock\n", i.name)
i.inStock = true
i.notifyAll()
}
func (i *item) register(o observer) {
i.observerList = append(i.observerList, o)
}
func (i *item) deregister(o observer) {
i.observerList = removeFromSlice(i.observerList, o)
}
func (i *item) notifyAll() {
for _, observer := range i.observerList {
observer.update(i.name)
}
}
func removeFromSlice(observerList []observer, observerToRemove observer) []observer {
observerListLength := len(observerList)
for i, observer := range observerList {
if observerToRemove.getID() == observer.getID() {
observerList[observerListLength-1], observerList[i] = observerList[i], observerList[observerListLength-1]
return observerList[:observerListLength-1]
}
}
return observerList
}
customer.go:
import "fmt"
type customer struct {
id string
}
func (c *customer) update(itemName string) {
fmt.Printf("Sending email to customer %s for item %s\n", c.id, itemName)
}
func (c *customer) getID() string {
return c.id
}
在上面的代码中item是subject的实现,customer是observer实现。
看下场景类main.go:
func main() {
shirtItem := newItem("GoLang Design Patterns")
observerFirst := &customer{id: "robin@zhyea.com"}
observerSecond := &customer{id: "golang@zhyea.com"}
shirtItem.register(observerFirst)
shirtItem.register(observerSecond)
shirtItem.updateAvailability()
}
执行后输出内容为:
Item GoLang Design Patterns is now in stock
Sending email to customer robin@zhyea.com for item GoLang Design Patterns
Sending email to customer golang@zhyea.com for item GoLang Design Patterns
代码已上传至GitHub: zhyea / go-patterns / observer-pattern
END!
GoLang设计模式13 - 观察者模式的更多相关文章
- 乐在其中设计模式(C#) - 观察者模式(Observer Pattern)
原文:乐在其中设计模式(C#) - 观察者模式(Observer Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 观察者模式(Observer Pattern) 作者:weba ...
- 设计模式之观察者模式(Observable与Observer)
设计模式之观察者模式(Observable与Observer) 好久没有写博客啦,之前看完了<设计模式之禅>也没有总结一下,现在回忆一下设计模式之观察者模式. 1.什么是观察者模式 简单情 ...
- 8.5 GOF设计模式四: 观察者模式Observer
GOF设计模式四: 观察者模式Observer 现实中遇到的问题 当有许多不同的客户都对同一数据源感兴趣,对相同的数据有不同的处理方式,该如 何解决?5.1 定义: 观察者模式 观察者模式 ...
- Golang设计模式—简单工厂模式(Simple Factory Pattern)
Golang设计模式--简单工厂模式 背景 假设我们在做一款小型翻译软件,软件可以将德语.英语.日语都翻译成目标中文,并显示在前端. 思路 我们会有三个具体的语言翻译结构体,或许以后还有更多,但现在分 ...
- php 设计模式之观察者模式(订阅者模式)
php 设计模式之观察者模式 实例 没用设计模式的代码,这样的代码要是把最上面那部分也要符合要求加进来,就要修改代码,不符合宁增不改的原则 介绍 观察者模式定义对象的一对多依赖,这样一来,当一个对象改 ...
- [JS设计模式]:观察者模式(即发布-订阅者模式)(4)
简介 观察者模式又叫发布---订阅模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知. 举一个现实生活中的例子,例如小 ...
- 数据结构和算法(Golang实现)(13)常见数据结构-可变长数组
可变长数组 因为数组大小是固定的,当数据元素特别多时,固定的数组无法储存这么多的值,所以可变长数组出现了,这也是一种数据结构.在Golang语言中,可变长数组被内置在语言里面:切片slice. sli ...
- 实践GoF的23种设计模式:观察者模式
摘要:当你需要监听某个状态的变更,且在状态变更时通知到监听者,用观察者模式吧. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:观察者模式>,作者: 元闰子 . 简介 现在有 ...
- java设计模式之观察者模式
观察者模式 观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式.模型-视图(View)模式.源-收听者(Listener)模式或从属者模式)是软件设计模式的一种.在此种模 ...
随机推荐
- urllib2获取CGI请求的数据
import urllib.request as urllib2 headers = { 'Authorization': 'Basic YWRtaW46YWRtaW4=', }#需要身份验证时,在请 ...
- P2012-拯救世界2【EGF】
正题 题目链接:https://www.luogu.com.cn/problem/P2012 题目大意 \(12\)种东西排列成长度为\(n\)的序列,要求前四种出现奇数次,后四种出现偶数次,求方案. ...
- P3645-[APIO2015]雅加达的摩天楼【bfs,根号分治】
正题 题目链接:https://www.luogu.com.cn/problem/P3645 题目大意 \(n\)个点,\(m\)条狗,第\(i\)条狗可以往左或者右跳恰好\(p_i\)步,开始是\( ...
- Android QMUI实战:沉浸式/适配状态栏
近期研究QMUI换肤的实现,顺便分析了下QMUI的沉浸式. 网上已有很多关于QMUI实现页面沉浸式的文章,简而言之:复杂了. 本期,我们仅通过几行代码,即可完美实现页面沉浸式效果,并轻松匹配换肤的色彩 ...
- websocket方案调研及实践
目录 webscoket方案调研及实践 一.使用场景 二.方案调研 1.Ajax短轮询 2.long-polling长轮询 3.iframe长连接 4.XHR-streaming 5.Websocke ...
- [JUC-5]ConcurrentHashMap源码分析JDK8
在学习之前,最好先了解下如下知识: 1.ReentrantLock的实现和原理. 2.Synchronized的实现和原理. 3.硬件对并发支持的CAS操作及JVM中Unsafe对CAS的实现. 4. ...
- java---String 和 StringBuffer
Java-String和StringBuffer类 Java String 类 字符串在Java中属于对象,Java提供String类来创建和操作字符串. 创建字符串 创建字符串常用的方法如下: ...
- 【数据结构与算法Python版学习笔记】树——相关术语、定义、实现方法
概念 一种基本的"非线性"数据结构--树 根 枝 叶 广泛应用于计算机科学的多个领域 操作系统 图形学 数据库 计算机网络 特征 第一个属性是层次性,即树是按层级构建的,越笼统就越 ...
- Java:并发笔记-05
Java:并发笔记-05 说明:这是看了 bilibili 上 黑马程序员 的课程 java并发编程 后做的笔记 4. 共享模型之内存 本章内容 上一章讲解的 Monitor 主要关注的是访问共享变量 ...
- qwt使用细节
在使用QWT进行二维曲线绘制,使用方法如下: class Plot: public QwtPlot { Q_OBJECT -- } 报错:error LNK2001: 无法解析的外部符号"p ...