作用:定義對象之間的一對多依賴,當一個對象狀態改變時,它的所有依賴都會收到通知並且自動更新狀態。
主題(Subject)是被觀察的對象,而其所有依賴者(Observer)稱爲觀察者。
類圖:主題(Subject)具有註冊和移除觀察者、並通知所有觀察者的功能,主題是通過維護一張觀察者列表來實現這些操作的。
觀察者(Observer)的註冊功能需要調用主題的 registerObserver() 方法。
案例:天氣數據佈告板會在天氣信息發生改變時更新其內容,佈告板有多個,並且在將來會繼續增加。
實現:
//client.go
package main
func main() {
var concreteSubject = new(ConcreteSubject)
concreteSubject.New() // 主題類初始化
var concreteObserver1 = new(ConcreteObserver1)
concreteObserver1.RegisterToSubject(concreteSubject) // 註冊觀察者1
var concreteObserver2 = new(ConcreteObserver2)
concreteObserver2.RegisterToSubject(concreteSubject) // 註冊觀察者2
concreteSubject.SetMeasurements(0,0,0) // 主題更新,通知觀察者
concreteSubject.SetMeasurements(1,1,1) // 主題更新,通知觀察者
}
//output。。。
//ConcreteObsever1.update: 0 0 0
//ConcreteObsever2.update: 0 0 0
//ConcreteObsever1.update: 1 1 1
//ConcreteObsever2.update: 1 1 1
//Observe.go
package main
import "fmt"
type Observer interface { // 接口是指針類型
Update(t,h,p float64) // 更新觀察者
}
type ConcreteObserver1 struct { // 結構體是值類型,在函數中非指針傳遞時,屬於拷貝,任何修改都不會保留
}
func (this *ConcreteObserver1) Update(t,h,p float64) { // 更新
fmt.Println("ConcreteObsever1.update: ", t ," ", h ," ", p)
}
func (this *ConcreteObserver1) RegisterToSubject(subject Subject) {
subject.RegisterObserver(this)
}
type ConcreteObserver2 struct {
}
func (this *ConcreteObserver2) Update(t,h,p float64) {
fmt.Println("ConcreteObsever2.update: ", t ," ", h ," ", p)
}
func (this *ConcreteObserver2) RegisterToSubject(subject Subject) {
subject.RegisterObserver(this)
}
//Subject
package main
type Subject interface { // 主題類
RegisterObserver(observer Observer) // 註冊觀察者
RemoveObserver(observer Observer) // 移除觀察者
NotifyObserver() // 通知所有觀察者
}
type ConcreteSubject struct {
Temperature float64
Humidity float64
Pressure float64
Observers []Observer
}
func (this *ConcreteSubject) New() { // 初始化
this.Observers = make([]Observer,0)
}
func (this *ConcreteSubject) RegisterObserver(observer Observer) {
this.Observers = append(this.Observers, observer)
}
func (this *ConcreteSubject) RemoveObserver(observer Observer) {
for i:=0 ;i<len(this.Observers); i++ {
if this.Observers[i] == observer {
this.Observers = append(this.Observers[:i],this.Observers[i+1:]...)
}
}
}
func (this *ConcreteSubject) SetMeasurements(t,h,p float64) { // 更新主題屬性
this.Temperature = t
this.Humidity = h
this.Pressure = p
this.NotifyObserver()
}
func (this *ConcreteSubject) NotifyObserver() {
for i:=0; i<len(this.Observers); i++ {
twmp := this.Observers[i]
twmp.Update(this.Temperature,this.Humidity,this.Pressure)
}
}