返回首页

简介
观察者模式(也称为quot;发布的Subscribequot;或quot;主题Observerquot;模式)是最知名的开发者社区的模式之一。也有不少文章谈论它。如果你不是很熟悉的Observer模式,你可能想第一检查{A}。在这篇文章中,我想表现出的稍微更为稳定,这是非常有用的和节省时间,在处理动态变化的主题观察员关系的观察者模式的版本。
在一个标准的实施,主体持有的附加观察员的指针数组。附加观察员应明确quot; detachquot;临终前从主体本身。因此,观察家需要引用以某种方式的主题。正如你可能会意识到,双方举行了相互之间的引用。如果任何主题或观察员在沉默中死亡 - 比方说,抛出异常跳过"分离"的号召。悬摆指针!
我的模板实现为您提供:一名观察员不科目,主题之前,其所附的观察员默默地死去。我的模板还提供了标准的功能 - 自动执行作为支撑的代码(例如,安装/卸下,并通知)。实施
附带的源代码应该解释本身。在这里,我想表现出一些基本思路。
{S0}
在如上图所示,双方向列表是用于每个主题。双方向列表的好处是可以随时脱链本身的观察员。因此脱钩的功能可以被称为观察员,以确保没有悬挂指针左侧列表中的析构函数。
观察员本身实际上是不直接链接到该列表。相反,一个观察员,拥有一个可连接的节点的数组,在打开链接到列表中。节点也充当代理转发通知消息给其所有者,观察员。使用代码
使用模板很简单。之前,我告诉你一个简单的例子,请确保您已安装Boost库。比方说,在股市中的应用,你需要写一个价格监测(观察员),提醒用户时,最新的贸易价格变动。下面显示的是需要实现的接口。

struct PriceChangeListener

{

 virtual void OnChange(double latest_price) = 0;

};

价格监测看起来像这样:{C}
内容的主题看起来像这样:
#include <boost/bind.hpp>

class PricePublisher : public SubjectSourceImpl<PriceChangeListener>

{

public:

 void SetLastestPrice(double latest_price_))

 {

   NotifyChanges(double latest_price_));  

 }



private:

 void NotifyChanges(double latest_price_)

 {

  TravelObservers(boost::bind(&PriceChangeListener::OnChange, _1, latest_price_)));

 }

}

请注意,所有的附加和分离PricePublisher功能提供的SubjectSourceImpl模板。 PricePublisher需要实现的唯一功能是NotifyChanges,调用的附加观察员的OnChange功能。在这里,我使用boost::绑定,以简化调用。
下面的代码片段显示了如何将观察员科目。
PricePublisher subject_A;

{ 

 PriceMoniter observer_1; 

 subject_A.Attach(&observer_1); 

 // processing ... 

 // ... 

 // ... 

 subject_A.SetLastestPrice(2.35); //trigger observer 1

}

PriceMoniter observer_2;

subject_A.Attach(&observer_2);

subject_A.SetLastestPrice(2.40); //trigger observer 2 only

//....

局部变量observer_1是块内,这将是块销毁。你可以看到,有没有需要quot; detachquot; observer_1。
正如您可能会注意到,代码是比标准的Observer模式实现短。因此,与这些模板您的乐趣。请注意尽量不要在不同的线程创建观察员和主题,因为我没有实施任何互斥操作时,操作链表。当然,你可以自由添加你自己的这个功能。我用的是boost库,以减轻我的日常生活。如果你是Boost库不舒服,也觉得自由切换到升压的版本。

回答

评论会员:ahandke 时间:2011/12/07
喜马兮,

具有BCC编译器,我得到一个错误,声称typename的
需要声明ObserverNode:

template<class InterfaceT, bool multiple_links = true>

class LinkableObserverImpl: public LinkableObserverImplBase_<InterfaceT>

{

...

	ObserverNode* GetLinkNode()  //error!

	{

		LinkNodePtr new_ptr(new ObserverNode(this));

		link_nodes.push_back(new_ptr);

		return new_ptr.get();

	}

...

当我有资格在所有派生类ObserverNode:

的typedef typename的LinkableObserverImplBase_:ObserverNode ObserverNode;
编译。请看看:

"http://www.cpptalk.net/visibility-of-inherited-typedefs-vt10002.html"

否则,代码看起来非常好,很容易使用。
谢谢!

至于
阿尔弗雷德
评论会员:麻希 时间:2011/12/07
感谢,指出的问题。我没有在其他的编译器编译源,虽然我觉得C标准似乎支持无类型名称。你自由地作出自己的改变
评论会员:麻希 时间:2011/12/07
有任何意见,都表示热烈欢迎,特别是那些评级低本文。