2、观察者模式 Observer Pattern

观察者模式,定义了对象支架的一对多依赖,这样一来,当一个对象改变状态时,他的所有依赖者都会周到通知并自动更新。
其实就是一个数据源,其他观察值都订阅这个数据源并提供一个统一的数据更新方法供数据源数据更新的时候发送通知给各位观察者。
精髓就是所有观察者必须实现一个统一的update方法。
废话不多说了,其实理解到这个程度基本就OK了。

为了交互对象之间的松耦合设计而努力。

image.png

发个例子:气象数据变化于展示
数据源:气象数据WeatherData
观察者:气象展示CurrentDisplay
数据对象实现的接口:subject
观察者实现的接口:observer
数据展示实现的接口:displayElement
subject

//主题接口
type subject interface {
    RegisterObserver(observer)
    RemoveObserver(observer)
    notifyObserver()
}

这里我们需要定义3个方法,注册,注销,通知
observer

//订阅者接口
type observer interface {
    update(subject2 subject)
}

这里我们只需要定义一个更新数据的方法即可
displayElement

//展示接口
type displayElement interface {
    Display()
}

这里我们需要定义一个公共的展示方法用于数据展示
WeatherData

//天气对象
type WeatherData struct {
    subject
    //温度,湿度,气压
    temperature,humidity,pressure float64
    observers *list.List
}
//构造函数
func NewWeatherData() *WeatherData {
    instance  := new(WeatherData)
    instance.observers = list.New()
    return instance
}
//订阅
func (this *WeatherData) RegisterObserver(observer1 observer)  {
    this.observers.PushBack(observer1)
}
//取消订阅
func (this *WeatherData) RemoveObserver(observer1 observer)  {
    for ob := this.observers.Front(); ob != nil; ob = ob.Next() {
        if ob.Value.(*CurrentDisplay) == observer1.(*CurrentDisplay) {
            this.observers.Remove(ob)
            break
        }
    }
}
//通知
func (this *WeatherData) notifyObserver()  {
    for ob := this.observers.Front(); nil != ob; ob = ob.Next() {
        ob.Value.(observer).update(this)
    }
}
//信息更新方法
func (this *WeatherData) SetMeasurements(temperature float64,humidity float64,pressure float64) {
    this.temperature = temperature
    this.humidity = humidity
    this.pressure = pressure
    this.notifyObserver()
}

数据对象,除了数据属性,还有subject的方法,我们还需要一个更新数据的方法
CurrentDisplay

//当前气象
type CurrentDisplay struct {
    observer
    displayElement
    temperature,humidity,pressure float64
}
//更新
func (this *CurrentDisplay)update(subject2 subject)  {
    this.temperature = subject2.(*WeatherData).temperature
    this.humidity = subject2.(*WeatherData).humidity
    this.pressure = subject2.(*WeatherData).pressure
    this.Display()
}
//信息展示
func (this *CurrentDisplay)Display()  {
    fmt.Println("当前气温:" + strconv.FormatFloat(this.temperature, 'f',2,64))
    fmt.Println("当前湿度:" + strconv.FormatFloat(this.humidity, 'f',2,64))
    fmt.Println("当前气压:" + strconv.FormatFloat(this.pressure, 'f',2,64))
}

当前气象展示,实现update和Display接口
一切都准备好了,我们主函数测试下,这里为了省事只写了一个CurrentDisplay的观察者,实际上我们还可以定义很多,比如最高气温,平均气温等等。
为了看效果,主函数里初始化了两个CurrentDisplay,这样可以看出订阅和取消的效果

func main() {
    //气象信息
    weatherData := observerPattern.NewWeatherData()
    //当前气象1
    currentDisplay1 := new(observerPattern.CurrentDisplay)
    weatherData.RegisterObserver(currentDisplay1)
    //更新气象信息
    println("第一次气象信息更新")
    weatherData.SetMeasurements(30.23,24.01,36.52)
    //当前气象2
    currentDisplay2 := new(observerPattern.CurrentDisplay)
    weatherData.RegisterObserver(currentDisplay2)
    //更新气象信息
    println("第二次气象信息更新")
    weatherData.SetMeasurements(29.96,23.64,37.01)
    //currentDisplay1取消订阅weatherData
    weatherData.RemoveObserver(currentDisplay1)
    //更新气象信息
    println("第三次气象信息更新")
    weatherData.SetMeasurements(31.11,25.65,37.25)
}

执行以下,结果:

第一次气象信息更新
当前气温:30.23
当前湿度:24.01
当前气压:36.52
第二次气象信息更新
当前气温:29.96
当前湿度:23.64
当前气压:37.01
当前气温:29.96
当前湿度:23.64
当前气压:37.01
第三次气象信息更新
当前气温:31.11
当前湿度:25.65
当前气压:37.25
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,946评论 6 518
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 95,336评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 169,716评论 0 364
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,222评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 69,223评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,807评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,235评论 3 424
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,189评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,712评论 1 320
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,775评论 3 343
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,926评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,580评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,259评论 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,750评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,867评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,368评论 3 379
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,930评论 2 361