观察者模式
定义
它定义了一种对象之间的一对多的依赖关系。当一个对象的状态产生扭转时,所有依赖于它的对象都会失去告诉并自动更新。这种模式次要包含两类角色:主题(Subject)和观察者(Observer)。
观察者模式能够用一个现实生活中的例子来解释:杂志订阅。
假如有一家杂志出版社,负责出版一本杂志。这家出版社有很多订阅者。当每期杂志出版时,出版社须要将杂志寄给所有的订阅者。在这个过程中,出版社就是“主题”,订阅者们则是“观察者”。
主题(出版社)与观察者(订阅者)之间存在一种依赖关系。当主题有新的杂志出版时,所有依赖于它的观察者都会失去告诉,并收到新的杂志。订阅者能够随时勾销订阅,这时出版社会将他们从观察者名单中移除,当前新的杂志就不再寄给他们。
观察者模式就是这样一种设计模式,当一个对象(主题)的状态发生变化时,所有依赖于它的对象(观察者)都会失去告诉并自动更新。这种模式使得主题和观察者之间的依赖关系涣散,使得它们能够独立变动,升高了零碎的耦合度。
示意图
UML diagram
Subject(主题)
|----------------|----------------|
| | |
Observer1 Observer2 Observer3
在这个示意图中,主题(Subject)是观察者们依赖的对象。当 Subject 的状态发生变化时,所有依赖于它的观察者(Observer1,Observer2,Observer3)都会失去告诉并自动更新。
例子
package main
import "fmt"
// Subject 接口
type Subject interface {Register(observer Observer)
Unregister(observer Observer)
Notify()}
// Observer 接口
type Observer interface {Update(message string)
}
// ConcreteSubject 具体主题
type ConcreteSubject struct {observers []Observer
message string
}
func (s *ConcreteSubject) Register(observer Observer) {s.observers = append(s.observers, observer)
}
func (s *ConcreteSubject) Unregister(observer Observer) {
for i, obs := range s.observers {
if obs == observer {s.observers = append(s.observers[:i], s.observers[i+1:]...)
break
}
}
}
func (s *ConcreteSubject) Notify() {
for _, observer := range s.observers {observer.Update(s.message)
}
}
func (s *ConcreteSubject) SetMessage(message string) {
s.message = message
s.Notify()}
// ConcreteObserver 具体观察者
type ConcreteObserver struct {
id int
message string
}
func (o *ConcreteObserver) Update(message string) {
o.message = message
fmt.Printf("Observer %d received message: %s\n", o.id, o.message)
}
func main() {subject := &ConcreteSubject{}
observer1 := &ConcreteObserver{id: 1}
observer2 := &ConcreteObserver{id: 2}
subject.Register(observer1)
subject.Register(observer2)
subject.SetMessage("Hello, Observer!")
subject.Unregister(observer1)
subject.SetMessage("Observer1 has left.")
}
在这个例子中,ConcreteSubject
是具体主题,实现了 Subject 接口,具备注册、登记和告诉观察者的办法。ConcreteObserver
是具体观察者,实现了 Observer
接口,具备更新本身状态的办法。