观察者模式的具体概念原理,参见https://baike.baidu.com/item/%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F/5881786?fr=aladdin,讲的很详细。

下面是Golang实现的观察者模式,有五个文件(都在src/designer/observe/目录下),分别是:

1. defs.go : 定义被观察者和观察者接口

 package observe

 // 被观察者接口
type Subject interface {
Notify() // 当被观察者状态变更时,通知所有已注册的观察者,调用其自身的变更方法
State() int // 查看被观察者此时的状态
SetState(int) // 变更被观察者的状态
AddObserve(ob Observer) // 注册观察者
RemoveObserve(ob Observer) // 删除观察者
} // 观察者接口
type Observer interface {
Update(int) // 每个观察者要实现的变更自身的方法
}

2. subject_a.go : 一个被观察者实例,实现被观察者接口

 package observe

 // 一个被观察者对象
type SubjectA struct {
state int // 观察者监听的状态数据
observers []Observer // 存储已注册的观察者对象的容器
} // 实现查看当前被观察者对象的状态
func (sa *SubjectA) State() int {
return sa.state
} // 实现更改被观察者对象的状态
func (sa *SubjectA) SetState(state int) {
sa.state = state
} // 注册观察者
func (sa *SubjectA) AddObserve(ob Observer) {
sa.observers = append(sa.observers, ob)
} // 删除观察者
func (sa *SubjectA) RemoveObserve(ob Observer) {
for i, sao := range sa.observers {
if sao == ob {
sa.observers = append(sa.observers[:i], sa.observers[i+:]...)
}
}
} // 通知所有已注册的观察者,变更自身的状态
func (sa *SubjectA) Notify() {
for _, sao := range sa.observers {
sao.Update(sa.state)
}
} // 创建被观察者对象
func NewSubjectA(state int) *SubjectA {
return &SubjectA{state: state, observers: []Observer{}}
}

3. observe_a.go: 一个观察者实例,实现观察者接口

 package observe

 // 一个观察者对象
type ObserveA struct {
selfStatus int
} // 更新自身状态
func (oa *ObserveA) Update(state int) {
oa.selfStatus = state
} // 创建观察者对象实例
func NewObserveA(state int) *ObserveA {
return &ObserveA{selfStatus: state}
}

4. observe_b.go: 另一个观察者实例,实现观察者接口

 package observe

 // 一个观察者对象
type ObserveB struct {
selfStatus int
} // 更新自身状态
func (oa *ObserveB) Update(state int) {
oa.selfStatus = state
} // 创建观察者对象实例
func NewObserveB(state int) *ObserveB {
return &ObserveB{selfStatus: state}
}

5. observe_test.go: 测试文件

 package observe

 import (
"fmt"
"testing"
) func TestObserve(t *testing.T) {
sa := NewSubjectA()
oa := NewObserveA()
ob := NewObserveB() fmt.Println(sa.State())
fmt.Println(oa.selfStatus)
fmt.Println(ob.selfStatus) fmt.Println("modify state")
sa.SetState()
fmt.Println(sa.State()) fmt.Println("Add ob")
sa.AddObserve(oa)
sa.AddObserve(ob) sa.Notify()
fmt.Println("notify")
fmt.Println(sa.State())
fmt.Println(oa.selfStatus)
fmt.Println(ob.selfStatus)
}

测试结果:

jerry@jerry-TravelMate-P243:~/golearn/src/designer/observe$ go test -v
=== RUN TestObserve
2
3
4
modify state
5
Add ob
notify
5
5
5
--- PASS: TestObserve (0.00s)
PASS
ok designer/observe 0.002s
 
 
 
 
 
 

观察者模式之Golang实现的更多相关文章

  1. GoLang设计模式13 - 观察者模式

    观察者模式是一种行为型设计模式.这种模式允许一个实例(可以称为目标对象)发布各种事件(event)给其他实例(观察者).这些观察者会对目标对象进行订阅,这样每当目标对象发生变化时,观察者就会收到事件( ...

  2. Go语言实现-观察者模式

    前前言 这个类经过我的正式投入使用啊,发现不对劲,这样做可能会导致线程死锁 比如你dispatch一个event,然后在这个回调里把那个事件的侦听给remove掉了,那么就会导致线程死锁(这个问题找了 ...

  3. Golang, 以17个简短代码片段,切底弄懂 channel 基础

    (原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...

  4. 说说Golang的使用心得

    13年上半年接触了Golang,对Golang十分喜爱.现在是2015年,离春节还有几天,从开始学习到现在的一年半时间里,前前后后也用Golang写了些代码,其中包括业余时间的,也有产品项目中的.一直 ...

  5. TODO:Golang指针使用注意事项

    TODO:Golang指针使用注意事项 先来看简单的例子1: 输出: 1 1 例子2: 输出: 1 3 例子1是使用值传递,Add方法不会做任何改变:例子2是使用指针传递,会改变地址,从而改变地址. ...

  6. 23种设计模式--观察者模式-Observer Pattern

    一.观察者模式的介绍      观察者模式从字面的意思上理解,肯定有两个对象一个是观察者,另外一个是被观察者,观察者模式就是当被观察者发生改变得时候发送通知给观察者,当然这个观察者可以是多个对象,在项 ...

  7. Golang 编写的图片压缩程序,质量、尺寸压缩,批量、单张压缩

    目录: 前序 效果图 简介 全部代码 前序: 接触 golang 不久,一直是边学边做,边总结,深深感到这门语言的魅力,等下要跟大家分享是最近项目 服务端 用到的图片压缩程序,我单独分离了出来,做成了 ...

  8. 谈谈JS的观察者模式(自定义事件)

    呼呼...前不久参加了一个笔试,里面有一到JS编程题,当时看着题目就蒙圈...后来研究了一下,原来就是所谓的观察者模式.就记下来...^_^ 题目 [附加题] 请实现下面的自定义事件 Event 对象 ...

  9. golang struct扩展函数参数命名警告

    今天在使用VSCode编写golang代码时,定义一个struct,扩展几个方法,如下: package storage import ( "fmt" "github.c ...

随机推荐

  1. Java设计模式菜鸟系列(一)策略模式建模与实现

    转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/39721563 今天開始咱们来谈谈Java设计模式. 这里会结合uml图形来解说,有对uml ...

  2. 防遗忘笔记,Fedora交叉编译window下的virt-iewer的汉化

    1. 汉化代码里的资源 virtviewer使用的是gettex的方案是标准的linux里国际化的方案.按道理仅仅须要改动virtualviewer/po/zh_CN.po的文件. 编译. 然后确认在 ...

  3. Linux 下查找文件或文件夹

    有些在我看来比较实用的命令,在这里记一下,避免每次都搜索一轮. 1.查找文件和文件夹 $ find . -name "mongo*" 从当前路径开始,向子目录查找名字含有 &quo ...

  4. 洛谷 P3806 点分治模板

    题目:https://www.luogu.org/problemnew/show/P3806 就是点分治~ 每次暴力枚举询问即可,复杂度是 nmlogn: 注意 tmp[0]=1 ! 代码如下: #i ...

  5. php排序函数测试

    1.sort,asort,arsort函数 十万个数的数组排序,用了0.17秒 $starttime=explode(' ',microtime());;for ($i=0; $i <10000 ...

  6. ARM VM安装Linux Diagnostic 2.3扩展

    目前创建的Azure Linux虚拟机默认安装的是LAD 3.0,如果客户有特殊需求,可以通过如下方法安装LAD 2.3 1.在Azure Portal卸载LAD 3.0 2.使用Azure Powe ...

  7. jquery实现图片预加载提高页面加载速度

    使用jquery实现图片预加载提高页面加载速度和用户体 我们在做网站的时候经常会遇到这样的问题:一个页面有大量的图片导致页面加载速度缓慢,经常会出现一个白页用户体验很不好.那么如何解决这个问题 呢?首 ...

  8. 机器学习——Day 3 多元线性回归

    写在开头 由于某些原因开始了机器学习,为了更好的理解和深入的思考(记录)所以开始写博客. 学习教程来源于github的Avik-Jain的100-Days-Of-MLCode 英文版:https:// ...

  9. “浪潮杯”第九届山东省ACM大学生程序设计竞赛重现赛 C-Cities

    题目描述:There are n cities in Byteland, and the ith city has a value ai. The cost of building a bidirec ...

  10. RESTful 设计理论

    RESTful 设计: 1.协议通信协议:https 2.域名部署在API专用域名下,除非API很简单(https://www.example.com/api)https://api.example. ...