观察者模式和虚拟模板化函数

时间:2015-10-23 01:38:57

标签: c++ templates polymorphism virtual observer-pattern

我进入了一个场景,我必须(我想到的最好的事情)使用虚拟模板化函数(用于多态),但据我所知,这是不可能的。

我选择“使用”虚拟模板化函数,因此我不需要使用指针和继承(对于观察部分)。我的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而不是基类?

1 个答案:

答案 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);
    }
};