我正忙于向旧版 C++ 应用程序添加通用观察者机制(使用 Visual Studio 2010,但不使用 .Net,因此 .Net 委托是不可能的)。
在设计中,我想尽可能地将特定于应用程序的部分与通用观察者机制分开。
实现观察者的最合乎逻辑的方式似乎是这样的:
class IDoThisObserver
{
public:
void handlDoThis(int arg1, int arg2) = 0;
};
对于每种类型的观察者(IDoThisObserver、IDoThatObserver、...),方法(handleDoThis、handleDoThat)的参数都是不同的。
以通用方式存储观察者的内容,如下所示:
template<typename T>
class ObserverContainer
{
public:
void addObserver (T &t) {m_observers.push_back(&t);}
private:
std::list<T*> m_observers;
};
调用观察者不能一概而论,因为每种观察者类型的参数都不同。
另一种方法是将所有参数“打包”到一个参数中,如下所示:
struct DoThisInfo
{
DoThisInfo (int arg1, int arg2) : m_arg1(arg1), m_arg2(arg2) {}
int m_arg1;
int m_arg2;
};
然后定义一个更通用的观察者,像这样:
template<typename T>
class IObserver
{
public:
void notify(const T &t) = 0;
};
然后这些观察者的集合将变成这样:
template<typename T>
class ObserverContainer
{
public:
void addObserver (IObserver<T> &obs) {m_observers.push_back(&obs);}
private:
std::list<IObserver<T>*> m_observers;
};
现在,更多的逻辑可以集中添加到这个 ObserverContainer 中,包括调用所有的观察者。调用的“发起者”只需要创建并填写通知结构。
想要从多种观察者继承的类,需要这样做:
class MyObserver : public IObserver<NotifyThis>, public IObserver<NotifyThat>
{
...
};
这些方法中的哪一种(具有多个显式参数或具有一个结构参数的观察者)看起来最好?这两种方法有什么优点或缺点吗?
编辑:我进一步研究了替代方法,插槽/信号方法似乎是另一个不错的选择。我应该知道插槽/信号中有什么重要的缺点吗?