1. 程式人生 > >設計模式之觀察者模式(C++)

設計模式之觀察者模式(C++)

設計模式之觀察者模式

觀察者模式定義了一種一對多的依賴關係,讓多個觀察者同時監聽某一個主題物件。這個主題物件在狀態發生變化時,會通知所有觀察者物件,使它們能夠自動更新自己。其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;
}

測試結果如下圖:
在這裡插入圖片描述