观察者模式—Observer
1.模式定义:
观察者模式(Observer ):定义对象间一种一对多的依赖关系,每当一个被观察对象状态改变时,则通知所有监听的观察者。
2.模式结构
- Observer:观察者
- ConcreteObserver:具体观察者
- Subject:被观察者
- ConcreteSubject、ConcreteSubjectB:具体被观察者
3.代码分析
- 3.1 main.cpp
#include"concrete_observer.hpp"
#include"concrete_subject.hpp"
#include<iostream>
using namespace std;
int main(int argc, const char** argv) {
ConcreteSubject cs;
ConcreteObserver* co = new ConcreteObserver();
ConcreteObserverB* cob = new ConcreteObserverB();
cout << "===========================" << endl;
cs.Attach(co);
cs.Attach(cob);
cs.DoSomething();
cout << "===========================" << endl;
cs.Detach(cob);
cs.DoSomething();
cout << "===========================" << endl;
return 0;
}
- 3.2 观察者: observer.hpp
#ifndef OBSERVER_HPP
# define OBSERVER_HPP
// 抽象观察者接口
class Observer
{
public:
virtual ~Observer(){}
virtual void Update() = 0;
};
#endif // OBSERVER_HPP
- 3.3 具体观察者: concreteObserver.hpp
#ifndef CONCRETE_OBSERVER_HPP
# define CONCRETE_OBSERVER_HPP
#include<iostream>
#include"observer.hpp"
using namespace std;
// 具体观察者
class ConcreteObserver: public Observer
{
public:
ConcreteObserver(){}
~ConcreteObserver(){}
void Update() {
cout << "ConcreteObserver::Update" << endl;
}
};
// 具体观察者B
class ConcreteObserverB: public Observer
{
public:
ConcreteObserverB(){}
~ConcreteObserverB(){}
void Update() {
cout << "ConcreteObserverB::Update" << endl;
}
};
#endif // CONCRETE_OBSERVER_HPP
- 3.4 被观察者: subject.hpp
#ifndef SUBJECT_HPP
# define SUBJECT_HPP
#include<iostream>
#include"observer.hpp"
using namespace std;
// 抽象被观察者接口
class Subject
{
public:
virtual ~Subject(){}
virtual void Attach(Observer* o) = 0;
virtual void Detach(Observer* o) = 0;
virtual void Notify() = 0;
};
#endif // SUBJECT_HPP
- 3.5 具体被观察者: concreteSubject.hpp
#ifndef CONCRETE_SUBJECT_HPP
# define CONCRETE_SUBJECT_HPP
#include<iostream>
#include<map>
#include"subject.hpp"
#include"observer.hpp"
using namespace std;
class ConcreteSubject: public Subject
{
private:
map<Observer*, bool> m_observers; // 观察者
public:
ConcreteSubject(){}
~ConcreteSubject(){
for (auto iter = m_observers.begin(); iter != m_observers.end(); ++iter) {
delete iter->first;
}
m_observers.clear();
}
void Attach(Observer* o){
m_observers[o] = true;
}
void Detach(Observer* o){
auto it = m_observers.find(o);
if (it != m_observers.end()) {
m_observers.erase(it);
}
}
void Notify(){
for (auto it = m_observers.begin(); it != m_observers.end(); ++it) {
it->first->Update();
}
}
void DoSomething() {
Notify();
}
};
#endif // CONCRETE_SUBJECT_HPP
- 3.6 实验结果:
===========================
ConcreteObserver::Update
ConcreteObserverB::Update
===========================
ConcreteObserver::Update
===========================
4.优缺点
-
4.1 优点
- 4.1.1 观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。
- 4.1.2 观察者模式在观察目标和观察者之间建立一个抽象的耦合。
- 4.1.3 观察者模式支持广播通信。
- 4.1.4 观察者模式符合“开闭原则”的要求。
-
4.2 缺点
- 4.2.1 如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间,设计时建议被观察者执行单一职责原则。
- 4.2.2 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
5.模式分析
-
5.1 观察者模式是将观察者和被观察者分离,并抽象出两个抽象类,使它们之间建立一种抽象耦合关系,使观察者扩展容易,以满足设计原则之开闭原则;
-
5.2 观察者模式又名订阅发布模式,具体被观察者实现了订阅的设置与取消,客户端可以动态灵活的开启和关闭订阅;
-
5.3 观察者模式是解决的一种一对多的关系,一(被观察者)变话,多(观察者)接受到变化通知。
6.实例:各种斯监视韩非子(go代码实现)
-
类图:
-
6.0: main.go
package main
import (
"fmt"
"./observer"
)
func test_observer() {
fmt.Println("==================")
hanfeizi := observer.NewHanFeiZi()
lisi := observer.NewLiSi()
liusi := observer.NewLiuSi()
wangsi := observer.NewWangSi()
hanfeizi.AddObserver(lisi)
hanfeizi.AddObserver(liusi)
hanfeizi.HaveBreakfase()
fmt.Println("==================")
hanfeizi.DeleteObserver(liusi)
hanfeizi.AddObserver(wangsi)
hanfeizi.HaveFun()
fmt.Println("==================")
}
func main() {
test_observer()
}
- 6.1:被观察者韩非子接口:ihanfeizi.go
package observer
// 被观察者韩非子接口
type IHanFeiZi interface {
HaveBreakfast()
HaveFun()
}
// 被观察者接口
type IObservable interface {
AddObserver(observer IObserver)
DeleteObserver(observer IObserver)
NotifyObservers(context string)
}
- 6.2: 被观察者-韩非子:hanfeizi.go
package observer
import "fmt"
// 被观察者-韩非子
type HanFeiZi struct {
Observers map[IObserver]bool // 观察者
}
func NewHanFeiZi() *HanFeiZi {
return &HanFeiZi{
Observers: map[IObserver]bool{},
}
}
func (hfz *HanFeiZi) HaveBreakfase() {
fmt.Println("HanFeiZi::HaveBreakfase")
hfz.NotifyObservers("HanFeiZi::HaveBreakfase")
}
func (hfz *HanFeiZi) HaveFun() {
fmt.Println("HanFeiZi::HaveFun")
hfz.NotifyObservers("HanFeiZi::HaveFun")
}
func (hfz *HanFeiZi) AddObserver(observer IObserver) {
hfz.Observers[observer] = true
}
func (hfz *HanFeiZi) DeleteObserver(observer IObserver) {
delete(hfz.Observers, observer)
}
func (hfz *HanFeiZi) NotifyObservers(context string) {
for observer := range hfz.Observers {
observer.Update(context)
}
}
- 6.3: 观察者接口:iobserver.go
package observer
// 观察者接口
type IObserver interface {
Update(context string)
}
- 6.4: 真实观察者:observer.go
package observer
import "fmt"
// 真实的观察者-李斯
type LiSi struct {
}
func NewLiSi() *LiSi {
return &LiSi{}
}
func (ls *LiSi) Update(context string) {
fmt.Println("LiSi::Update ", context)
}
// 真实观察者-刘斯
type LiuSi struct {
}
func NewLiuSi() *LiuSi {
return &LiuSi{}
}
func (ls *LiuSi) Update(context string) {
fmt.Println("LiuSi::Update ", context)
}
// 真实观察者-王斯
type WangSi struct {
}
func NewWangSi() *WangSi {
return &WangSi{}
}
func (ls *WangSi) Update(context string) {
fmt.Println("WangSi::Update ", context)
}
- 6.5 执行结果:
==================
HanFeiZi::HaveBreakfase
LiSi::Update HanFeiZi::HaveBreakfase
LiuSi::Update HanFeiZi::HaveBreakfase
==================
HanFeiZi::HaveFun
LiSi::Update HanFeiZi::HaveFun
WangSi::Update HanFeiZi::HaveFun
==================