我进入了一个场景,我必须(我想到的最好的事情)使用虚拟模板化函数(用于多态),但据我所知,这是不可能的。
我选择“使用”虚拟模板化函数,因此我不需要使用指针和继承(对于观察部分)。我的observable(subject)类是一个Parser:它解析一个XML文件,并且应该通知每个观察者找到的每个节点。每个XML节点都映射到一个类,例如:
// Maps the '?xml' tag
struct XML { int version; // other stuff... };
相反,如果我选择使用继承,我也会有这个类:
struct Node { // Probably blank? }
然后,XML类如下:
// Maps the '?xml' tag
struct XML : public Node { int version; // other stuff... };
我相信这会解决我的问题,但我不想处理指针,因为会有一个类(我正在解析XML)具有非指针属性(我也不希望它们成为指针) )。
以下是我使用非虚拟模板函数实现观察者模式的方法。这是行不通的。它只是我喜欢它的一个例子:
#include <iostream>
#include <vector>
enum Type { XML, // other xml tag types };
struct SomeXMLNode { int data; };
struct Observer {
// This is what Id like to make virtual
template<typename T>
void onObserved(T t, Type type)
{
std::cout << "[base] observing " << t.data << std::endl;
// 'Safely' cast t, according to the specified type
}
};
class Observable
{
public:
void attach(Observer* o) { observers.push_back(o); }
protected:
template<class Node>
void notify(Node node, Type type)
{
for (std::vector<Observer*>::iterator it = observers.begin(); it != observers.end(); it++) {
(*it)->onObserved(node, type);
}
}
Observable() {}
protected:
std::vector<Observer*> observers;
};
class Parser : public Observable
{
public:
void parse()
{
SomeXMLNode s;
s.data = 1234;
notify(s, Types::XML); // Notify all observers about 'some xml node' during the parsing
}
};
struct SomeLoadableClass : public Observer
{
void load()
{
Parser p;
p.attach(this);
p.parse();
}
template<typename T>
void onObserved(T t, Type type)
{
std::cout << "[derived] observing " << t.data << std::endl; // Will never(?) get called! :(
}
};
int main()
{
SomeLoadableClass m;
m.load();
return 0;
}
如果使用了继承,则onObserved和notify函数可以更改为:
void onObserved(Node* node, Types type) { }
void notify(Node* node, Types type) { }
上面的'Node'是一个结构,而不是我在另一个例子中使用的模板。
观察者模式甚至是这种任务的最佳方法吗?没有使用继承还有其他选择吗?如何在不声明虚拟的情况下让我的派生类调度onObserved而不是基类?
答案 0 :(得分:0)
Since Parser derieves from Observable, the protected members should be accessible within Parser.
class Parser : public Observable
{
public:
void parse()
{
SomeXMLNode s;
s.data = 1234;
std::vector<Observer*>::iterator it = observers.begin();
for (;it != observers.end(); it++)
it->onObserved(s, Types::XML);
}
};