1 定义
观察者模式(Observer):定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个柱体对象,这个柱体对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己
UML类图:
观察者模式包含四个角色:
- Subject(抽象目标):又称为主题,是被观察的对象
- ConcreteSubject(具体目标):抽象目标的子类,通常包含有经常发生改变的数据,当它的状态发生改变时,向其各个观察者发出通知
- Observer(抽象观察者):观察者将对观察目标的改变做出反应
- ConcreteObserver(具体观察者):具体观察者中维持一个指向具体目标对象的引用,它用于存储具体观察者的有关状态,这些状态和具体目标的状态保持一致
我们下面以上班(在上班的时候有些同事会看股票行情,有些还会看NBA,老板则偶尔会走动,前台秘书和同事的关系比较好,等老板出来走动的时候,她会通知每位同事)为例,其UML类图如下:
2 go语言实现
2.1 实现Subject接口以及ConcreteSuject
type Subject interface {
SetState(state string)
GetState() string
Attach(observer Observer)
Notify()
}
type Boss struct {
observer []Observer
state string
}
func (b *Boss) SetState(state string) {
b.state = state
}
func (b Boss) GetState() string {
return b.state
}
func (b *Boss) Attach(observer Observer) {
b.observer = append(b.observer, observer)
}
func (b Boss) Notify() {
for _, o := range b.observer {
o.Update()
}
}
type Secretary struct {
observer []Observer
state string
}
func (s *Secretary) SetState(state string) {
s.state = state
}
func (s Secretary) GetState() string {
return s.state
}
func (s *Secretary) Attach(observer Observer) {
s.observer = append(s.observer, observer)
}
func (s Secretary) Notify() {
for _, o := range s.observer {
o.Update()
}
}
2.2 实现Observer接口以及ConcreteObserver
type Observer interface {
Update()
}
type StockObserver struct {
name string
subject Subject
}
func (so StockObserver) Update() {
fmt.Printf("%s, %s 关闭炒股软件,开始工作\n", so.subject.GetState(), so.name)
}
type NBAObserver struct {
name string
subject Subject
}
func (no NBAObserver) Update() {
fmt.Printf("%s, %s 关闭NBA直播,开始工作\n", no.subject.GetState(), no.name)
}
2.3 使用工厂方法创建具体观察者和被观察者
func NewSubject(t string) Subject {
switch t {
case "boss":
return &Boss{}
case "secretary":
return &Secretary{}
default:
return nil
}
}
func NewObserver(t, name string, subject Subject) Observer {
switch t {
case "stock":
return &StockObserver{
name: name,
subject: subject,
}
case "nba":
return &NBAObserver{
name: name,
subject: subject,
}
default:
return nil
}
}
2.4 客户端调用
func main() {
//创建一个通知者
tSubject := observer.NewSubject("boss")
//创建两个观察者,并与通知者绑定
tObserverA := observer.NewObserver("stock", "张三", tSubject)
tObserverB := observer.NewObserver("nba", "李四", tSubject)
//通知者登记观察者
tSubject.Attach(tObserverA)
tSubject.Attach(tObserverB)
//通知者状态改变
tSubject.SetState("老板来了")
//通知者开始通知观察者
tSubject.Notify()
}