DesignPatternOberver观察者模式
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
标准定义
UML图
观察者模式包含四个角色
- Subject(抽象目标):又称为主题,是被观察的对象
- ConcreteSubject(具体目标):抽象目标的子类,通常包含有经常发生改变的数据,当它的状态发生改变时,向其各个观察者发出通知
- Observer(抽象观察者):观察者将对观察目标的改变做出反应
- ConcreteObserver(具体观察者):具体观察者中维持一个指向具体目标对象的引用,它用于存储具体观察者的有关状态,这些状态和具体目标的状态保持一致
实际案例
场景模拟
爱玩联盟,之前还了解过联盟一点点的背景故事。符文大陆的国家艾欧尼亚很垃圾,诺克萨斯牛逼,就要干艾欧尼亚。首先,打仗,莽之前要观察对面的国家状态,他们牛逼还打啥了。选中他们最弱的时候干
UML图
代码实现
package my
import "fmt"
type Subject interface {
Attach() // 添加观察者们
Notify(o Observer) // 通知观察者
}
type Ionia struct {
Name string
Observers []Observer // 一直默默注视他的人
State bool // 自己的状态 true: 表示自己状态很好,不能被攻击
}
func NewIonia() *Ionia {
return &Ionia{
Name: "艾欧尼亚",
Observers: make([]Observer, 0),
State: true,
}
}
func (i *Ionia) SetState(b bool) {
i.State = b
}
func (i *Ionia) GetState() bool {
return i.State
}
func (i *Ionia) Attach(o Observer) {
i.Observers = append(i.Observers, o)
}
func (i *Ionia) Notify() {
for _, observer := range i.Observers {
if i.State {
fmt.Println("艾欧尼亚现在牛逼不能进攻")
continue
}
observer.Update()
}
}
type Observer interface {
Update() // 根据情报做出相应的动作
}
type Noxus struct {
Name string
}
func NewNoxus() *Noxus {
return &Noxus{Name: "诺克萨斯"}
}
func (n *Noxus) Update() {
fmt.Println("攻打艾欧尼亚")
}
func TTmain() {
ionia := NewIonia()
noxus := NewNoxus()
ionia.Attach(noxus)
for i := 0; i <= 5; i++ {
if i%2 == 0 {
ionia.SetState(false)
} else {
ionia.SetState(true)
}
ionia.Notify()
}
}
# 测试ttmain()输出
攻打艾欧尼亚
艾欧尼亚现在牛逼不能进攻
攻打艾欧尼亚
艾欧尼亚现在牛逼不能进攻
攻打艾欧尼亚
艾欧尼亚现在牛逼不能进攻
业务拓展
场景模拟
如果是这样的话,太简单了。再来个场景: 诺克萨斯之前的罪过恕瑞玛。当诺克萨斯干别人时候,自己也是最空虚的时候。这时候就干他
核心点+疑难杂症
- 这时候,诺克萨斯变成了观察者,同时也变成了被观察者
- 所以,对线创建问题就出现了
- 还有接口就是一团,全部融合进去,既是观察者优势Subject,显然是不适用的