設計模式(三)觀察者模式Observer(釋出訂閱)

CalmReason發表於2016-03-15

本文程式碼來自陳碩《Linux 多執行緒服務端程式設計:使用 muduo C++ 網路庫》

觀察者模式的目的是讓部落格更新之後,所有訂閱了部落格的人都能得到通知

這裡使用了智慧指標來實現,從而完整的解決了資源管理的問題。

實現效果:



原始碼:

Blog.h

#pragma once
#include <string>
#include <iostream>
using namespace std;
#include <vector>
#include "boost/weak_ptr.hpp"

//#include "Observer.h"這裡不能包含標頭檔案,會迴圈引用
class Observer;//這裡只能使用前置宣告

class Blog
{
public:
	Blog()
	{
		cout<<"Blog()"<<endl;
	}
	~Blog(void);
	void set_name(const string& name)
	{
		name_ = name;
	}
	const string get_name()
	{
		return name_;
	}
	void set_status(const string& s)
	{
		status_ = s;
	}
	const string get_status(void) const
	{
		return this->status_;
	}
	void add_observer(const boost::shared_ptr<Observer>& pobserver)
	{
		observers_.push_back(pobserver);
	}
	void notify(void);

private:
	string name_;
	string status_;
	//這裡使用weak_ptr是僅僅引用資源,而不產生使用計數,防止迴圈引用而不能析構
	vector<boost::weak_ptr<Observer> > observers_;
	typedef vector<boost::weak_ptr<Observer> >::iterator iter;
};
Blog.cpp

#include "Blog.h"
#include "Observer.h"//在這裡包含標頭檔案
Blog::~Blog(void)
{
	cout<<"~Blog()"<<endl;
}

void Blog::notify(void)
{
	iter i = observers_.begin();
	//標準寫法
	while(i!=observers_.end())
	{
		//weak_ptr本身不具備訪問能力(單一職責),都是通過shared_ptr來實現
		boost::shared_ptr<Observer> pobserver(i->lock());
		//判斷物件是否已經析構
		if (pobserver)
		{
			pobserver->update();
			//迭代器在這裡前進
			++i;
		}
		//已經析構的物件不再引用
		else
		{
			i = observers_.erase(i);
		}
	}
}
Observer.h

#pragma once
#include <string>
#include <iostream>
using namespace std;
#include "Blog.h"
#include "boost/shared_ptr.hpp"
#include "boost/weak_ptr.hpp"

class Observer
{
public:
	//由於只能指標都是值語義的,所以使用常值引用可以減少複製
	Observer(const string& name,const boost::shared_ptr<Blog>& pblog)
		:name_(name),blog_(pblog)
	{
		cout<<"Observer("<<name_<<")訂閱了"<<blog_.lock()->get_name()<<endl;
	}
	~Observer(void)
	{
		cout<<"~Observer("<<name_<<")"<<endl;
	}
	void update(void)
	{
		cout<<name_<<"知道了"
			<<blog_.lock()->get_name()
			<<blog_.lock()->get_status()<<endl;
	}
private:
	string name_;
	//這裡使用weak_ptr是僅僅引用資源,而不產生使用計數,防止迴圈引用而不能析構
	boost::weak_ptr<Blog> blog_;
};
observer_main.cpp

#include "Blog.h"
#include "Observer.h"
#include "boost/shared_ptr.hpp"

int main()
{
	boost::shared_ptr<Blog> pblog(new Blog());
	pblog->set_name("CalmReason CSDN Blog");
	
	boost::shared_ptr<Observer> pobserver1(new Observer("張三",pblog));
	boost::shared_ptr<Observer> pobserver2(new Observer("李四",pblog));

	pblog->add_observer(pobserver1);
	pblog->add_observer(pobserver2);


	pblog->set_status("發表了部落格:C++的記憶體管理");
	pblog->notify();

	pblog->set_status("發表了部落格:weak_ptr的基本用法");
	pblog->notify();

	return 0;
}



相關文章