Observer 觀察者模式
在軟件構建過程中,我們需要爲某些對象建立一種“通知依賴關係” ——一個對象(目標對象)的狀態發生改變,所有的依賴對象(觀察者對象)都將得到通知。如果這樣的依賴關係過於緊密,將使軟件不能很好地抵禦變化
使用面向對象技術,可以將這種依賴關係弱化,並形成一種穩定的依賴關係。從而實現軟件體系結構的鬆耦合。
定義對象間的一種一對多(變化)的依賴關係,以便當一個對象(Subject)的狀態發生改變時,所有依賴於它的對象都得到通知並自動更新。
使用面向對象的抽象,Observer模式使得我們可以獨立地改變目標與觀察者,從而使二者之間的依賴關係達致鬆耦合。
目標發送通知時,無需指定觀察者,通知(可以攜帶通知信息作爲參數)會自動傳播
觀察者自己決定是否需要訂閱通知,目標對象對此一無所知
Observer模式是基於事件的UI框架中非常常用的設計模式,也是MVC模式的一個重要組成部分
golang
代碼:更改前
package obs
import "fmt"
type ProgressBar struct {}
func (p *ProgressBar) setValue(value float64) {
fmt.Println(value)
}
type FileSplitter struct {
Filename string
FileNumber int
Progress_bar *ProgressBar
}
func (f FileSplitter) Split() {
// 1. 讀取文件
// ....
// 2. 分批次向小文件寫入
for i:=0;i< f.FileNumber;i++{
// ....
// 設置進度
f.Progress_bar.setValue(float64((i+1))/float64(f.FileNumber))
}
}
代碼:更改後
package obs
type IProgram interface {
DoProgress(float64)
}
type IPrograms struct {
iprograms []*IProgram
}
func (ipr *IPrograms) OnProgress(value float64) {
for _,iprogram := range ipr.iprograms{
(*iprogram).DoProgress(value)
}
}
func (ipr *IPrograms) Append(program IProgram) {
ipr.iprograms = append(ipr.iprograms, &program)
}
func (ipr *IPrograms) Remove(program IProgram) {
for i,iprogram := range ipr.iprograms{
if iprogram == &program{
ipr.iprograms = append(ipr.iprograms[:i],ipr.iprograms[i+1:]...)
}
}
}
type FileSplitter struct {
Filename string
FileNumber int
IPrograms *IPrograms
}
func (f FileSplitter) Split() {
// 1. 讀取文件
// ....
// 2. 分批次向小文件寫入
for i:=0;i< f.FileNumber;i++{
// ....
// 設置進度
f.IPrograms.OnProgress(float64(i+1)/float64(f.FileNumber))
}
}
main.go
main.go
package main
import (
"Methods/observer/obs"
"fmt"
)
type ProgressBar struct {}
func (p ProgressBar) DoProgress(value float64) {
fmt.Println(value)
}
type ProgressCount struct {}
func (p ProgressCount) DoProgress(value float64) {
fmt.Printf("c_%v\n",value)
}
func main() {
var p obs.IPrograms
var pb = ProgressBar{}
var pc = ProgressCount{}
p.Append(pb)
p.Append(pc)
var f obs.FileSplitter = obs.FileSplitter{"test",5,&p}
f.Split()
}