文章目录
- [1. 概念](#1. 概念)
-
- [1.1 角色](#1.1 角色)
- [1.2 类图](#1.2 类图)
- [2. 代码示例](#2. 代码示例)
-
- [2.1 代码](#2.1 代码)
- [2.2 类图](#2.2 类图)
1. 概念
观察者(Observer)指当目标对象状态发生变化后,对状态变化事件进行响应或处理的对象。
1.1 角色
- Subject(抽象主题):
- 它可以有多个观察者,并将所有观察者对象的引用保存在一个集合里
- 被观察者提供一个接口,可以增加和删除观察者角色
- ConcreteSubject(具体主题):
- 将有关状态存入具体观察者对象
- 在主题发生改变时,给所有的观察者发出通知
- Observer(抽象观察者):
- 为所有的具体观察者定义一个更新接口,在收到主题的通知时能够及时的更新自己
- ConcreteObserver(具体观察者):
- 实现抽象观察者角色定义的更新接口,以便使本身的状态与主题状态相协调。如果需要,具体观察者角色可以保存一个指向具体主题角色的引用。
1.2 类图
Subject -observer:List +Add(o:Observer) +NotifyObserver() +ChangeState() ConcreteSubject +ChangeState() <<interface>> Observer +Update(s:State) ConcreteObserverA +Update(s:State) ConcreteObserverB +Update(s:State)
2. 代码示例
2.1 代码
- 代码
go
package main
import "fmt"
//定义抽象主题,它是观察者的聚合
type Subject struct{
observers []Observer
}
//定义一个方法,为抽象主题添加观察者
func (c *Subject) Attach(o ...Observer) {
c.observers = append(c.observers, o...)
}
//定义实际主题,继承抽象主题,它是实际的被观察者。
type ConcreteSubject struct {
Subject Subject
context string
}
//依次通知观察者
func (c *ConcreteSubject) notify() {
for _, o := range c.Subject.observers {
o.Update(c)
}
}
//具体抽象主题的,同时发送通知给观察者
func (c *ConcreteSubject) UpdateContext(context string) {
c.context = context
c.notify()
}
//定义抽象观察者
type Observer interface {
Update(*ConcreteSubject)
}
//定义具体观察者
type ConcreteObserverA struct {
name string
}
//更新观察者
func (r *ConcreteObserverA) Update(c *ConcreteSubject) {
fmt.Printf("%s receive %q\n", r.name, c.context)
}
//定义具体观察者
type ConcreteObserverB struct {
name string
}
//更新观察者
func (r *ConcreteObserverB) Update(c *ConcreteSubject) {
fmt.Printf("%s receive %q\n", r.name, c.context)
}
//定义具体观察者
type ConcreteObserverC struct {
name string
}
//更新观察者
func (r *ConcreteObserverC) Update(c *ConcreteSubject) {
fmt.Printf("%s receive %q\n", r.name, c.context)
}
func main() {
//实例化抽象主题
subject := Subject{
observers: make([]Observer, 0),
}
//实例化3观察者
concreteObserverA := &ConcreteObserverA{
name: "concreteObserverA",
}
concreteObserverB := &ConcreteObserverB{
name: "concreteObserverB",
}
concreteObserverC := &ConcreteObserverC{
name: "concreteObserverC",
}
//将3个观察者加入抽象主题
subject.Attach(concreteObserverA,concreteObserverB,concreteObserverC)
//实例化具体主题
concreteSubject := &ConcreteSubject{
Subject: subject,
}
//更新具体主题,它将通知所有观察者
concreteSubject.UpdateContext("updata context")
}
- 输出
shell
concreteObserverA receive "updata context"
concreteObserverB receive "updata context"
concreteObserverC receive "updata context"
2.2 类图
Subject +[]Observe observers +Attach(o ...Observer) ConcreteSubject +Subject:Subject +context:String +Notify() +UpdateContext(context string) <<interface>> Observer +Update(c *ConcreteSubject) ConcreteObserverA +Name:String +Update(c *ConcreteSubject) ConcreteObserverB +Name:String +Update(c *ConcreteSubject) ConcreteObserverC +Name:String +Update(c *ConcreteSubject)