設計模式之觀察者模式(C++)
阿新 • • 發佈:2019-02-12
設計模式之觀察者模式
觀察者模式定義了一種一對多的依賴關係,讓多個觀察者同時監聽某一個主題物件。這個主題物件在狀態發生變化時,會通知所有觀察者物件,使它們能夠自動更新自己。其UML圖如下:
在ConcretSubject內部有一個Observer的列表,當Subject的狀態發生改變時,會通知列表內的所有的觀察者。而觀察者都實現了統一的介面,而不同的觀察者在該介面中做出了不同的響應。其示例程式碼如下:
// ObserverModel.h檔案
#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
// 觀察者
class Observer
{
public:
virtual void Update() = 0;
};
class ConcreteObserver_0 : public Observer
{
public:
virtual void Update()
{
std::cout << "ConcreteObserver_0 知道了" << std::endl;
}
};
class ConcreteObserver_1 : public Observer
{
public:
virtual void Update()
{
std::cout << "ConcreteObserver_1 知道了" << std::endl;
}
};
// 通知者
class Subject
{
public:
virtual void Attatch(Observer * p) = 0;
virtual void Detach(Observer * p) = 0;
virtual void Notify() = 0;
virtual void changeState(std::string str)
{
m_str = str;
Notify();
}
protected:
std::string m_str;
};
// 傳統觀察者模式
class ConcreteSubject : public Subject
{
public:
ConcreteSubject()
{
;
}
~ConcreteSubject()
{
m_vec.clear();
}
virtual void Attatch(Observer * p)
{
m_vec.push_back(p);
}
virtual void Detach(Observer * p)
{
auto it = find(m_vec.begin(), m_vec.end(), p);
if (m_vec.end() != it)
{
m_vec.erase(it);
}
}
virtual void Notify()
{
for (auto it = m_vec.cbegin(); it != m_vec.cend(); it++)
{
std::cout << m_str << " ";
(*it)->Update();
}
}
private:
std::vector<Observer * > m_vec;
};
測試程式碼如下:
#include <iostream>
#include "ObserverModel.h"
int main()
{
using namespace std;
// 觀察者模式
ConcreteSubject * p = new ConcreteSubject();
Observer * p1 = new ConcreteObserver_0();
Observer * p2 = new ConcreteObserver_1();
p->Attatch(p1);
p->Attatch(p2);
p->changeState("老闆來啦");
delete p;
delete p2;
delete p1;
getchar();
return 0;
}
測試結果如下圖:
觀察者模式也有不足,觀察者模式需要觀察者需要實現相同的介面。但是如果已經些好的類或者第三方的類庫則就沒辦法實現該功能了。所以可以稍稍改進一下,就是把Subject類中的關於觀察者的列表修改為函式指標的列表。示例碼如下:
// ObserverModel.h檔案
#pragma once
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
// 函式指標版本
class ConcreteObserverFunc_0
{
public:
static void func_0()
{
std::cout << "ConcreteObserver_0 知道了" << std::endl;
}
};
class ConcreteObserverFunc_1
{
public:
static void func_1()
{
std::cout << "ConcreteObserver_1 知道了" << std::endl;
}
};
class SubjectFunc
{
public:
virtual void Attatch(void (*p)()) = 0;
virtual void Detach(void(*p)()) = 0;
virtual void Notify() = 0;
virtual void changeState(std::string str)
{
m_str = str;
Notify();
}
protected:
std::string m_str;
};
class ConcreteSubjectFunc : public SubjectFunc
{
private:
std::vector<void(*)()> m_func;
public:
ConcreteSubjectFunc()
{
;
}
~ConcreteSubjectFunc()
{
m_func.clear();
}
virtual void Attatch(void (*p)())
{
m_func.push_back(p);
}
virtual void Detach(void(*p)())
{
auto it = find(m_func.begin(), m_func.end(), p);
if (m_func.end() != it)
{
m_func.erase(it);
}
}
virtual void Notify()
{
for (auto it = m_func.cbegin(); it != m_func.cend(); it++)
{
std::cout << m_str << " ";
(*it)();
}
}
};
測試程式碼如下:
#include <iostream>
#include "ObserverModel.h"
int main()
{
using namespace std;
// 觀察者模式
ConcreteObserverFunc_0 * p1Func = new ConcreteObserverFunc_0();
ConcreteObserverFunc_1 * p2Func = new ConcreteObserverFunc_1();
ConcreteSubjectFunc * pFunc = new ConcreteSubjectFunc();
pFunc->Attatch(&ConcreteObserverFunc_0::func_0);
pFunc->Attatch(&ConcreteObserverFunc_1::func_1);
pFunc->changeState("我的天哪");
delete p1Func;
delete p2Func;
delete pFunc;
getchar();
return 0;
}
測試結果如下圖: