觀察者模式的實現

測試環境:visual studio 2017。

測試參數:標準符合:C++ 14 和 C++ 17

理論上也符合C++ 11。

EventWrap實現的是主題類(發佈者)

Observer的派生類是觀察者。

這個實現新穎的部分是:

1、類的特種函數的定義向C++新標準靠攏。自定義析構函數後(支持虛析構),添加移動操作函數(支持移動操作),添加冗餘的複製操作函數(新標準推薦的做法)。

2、採用智能指針。如果某個觀察者類銷燬,主題類能自動感知到,不進行消息發佈。智能指針的使用也保證某個觀察者對象執行Update期間this指針有效(在多線程環境下,它可能被銷燬導致this失效。)。當然目前這份源碼不會在多線程使用,還沒有保護observers_變量。

#include "pch.h"
#include <iostream>
#include <memory>
#include <list>
#include <string>
#include <chrono>

using namespace std;
using namespace std::chrono;

class EventPara
{
public:
	string name_;
};

class Observer
{
public:
	virtual void Update(EventPara para) = 0;
public:
	//按照C++標準的解釋,類中沒有用戶聲明的構造函數時編譯器生成默認構造函數。
	//在visual studio 2017運行時,因爲聲明瞭複製構造函數或賦值構造函數,導致編譯器沒有生成默認構造函數。
	//文檔中認爲這兩個函數不屬於構造函數,所以測試結果和文檔解釋存在衝突。
	Observer() = default;
	//虛析構保證子類析構
	virtual ~Observer() = default;

	//C++不推薦聲明析構函數而不聲明覆制操作
	Observer(const Observer&) = default;
	Observer& operator=(const Observer&) = default;

	//聲明瞭析構函數後,編譯器不默認生成移動操作函數
	Observer(Observer&&) = default;
	Observer& operator = (Observer&&) = default;

};

class Student : public Observer
{
public:
	void Update(EventPara para) override
	{
		cout << "Student " << this << para.name_ << endl;
	}
};

class Teacher : public Observer
{
public:
	void Update(EventPara para) override
	{
		cout << "Teacher " << this << para.name_ << endl;
	}
};

class EventWrap
{
public:
	void Register(weak_ptr<Observer> o)
	{
		observers_.emplace_back(o);
	}

	void Publish(EventPara& para)
	{
		for (auto& p : observers_)
		{
			auto ob = p.lock();
			if (ob)
			{
				ob->Update(para);
			}
		}
		observers_.remove_if([](weak_ptr<Observer>& o)
				    {
					if (o.expired())
				        {
					    return true;
					}
					return false;
				    });
	}
	int Count()
	{
		return observers_.size();
	}
private:
	list<weak_ptr<Observer>> observers_;
};

int main()
{
	EventWrap e;

	EventPara para;
	{
		shared_ptr<Student> stu1 = make_shared<Student>();
		shared_ptr<Student> stu2 = make_shared<Student>();
		shared_ptr<Teacher> tea1 = make_shared<Teacher>();

		e.Register(stu1);
		e.Register(stu2);
		e.Register(tea1);

		para.name_ = " 動態生成的參數:" + to_string(steady_clock::now().time_since_epoch().count());
		cout << e.Count() << endl;
		e.Publish(para);
		cout << e.Count() << endl;

	}
	shared_ptr<Student> stu3 = make_shared<Student>();
	shared_ptr<Teacher> tea2 = make_shared<Teacher>();
	e.Register(stu3);
	e.Register(tea2);
	para.name_ = " 動態生成的參數:" + to_string(steady_clock::now().time_since_epoch().count());
	cout << e.Count() << endl;
	e.Publish(para);
	cout << e.Count() << endl;
	return 0;
}

 執行結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章