Home > Blockchain >  Passing the template variable to the Observers from the Subject - Observe design pattern
Passing the template variable to the Observers from the Subject - Observe design pattern

Time:09-10

I am utilizing an observer design pattern for this simple use case whereupon a change in a Subject concrete class, the template value _x is passed to the observers via notify() however that will require Subject to be a template class which I don't want.

Instead of making Subject a template class, I made notify a template function and made Observer a template to allow the passing of a template value in update() but that will cause problems inside Subject which doesn't need to be a template class.

Any ideas on getting around this problem without making Subject template?

class Subject;

template<typename T>
class Observer
{
    public:
    virtual void update(T value, Subject *) = 0;
};

class Subject
{
    std::vector<Observer<T>*> _obs;

    public:
    void attach(Observer<T>* obs)
    {
        _obs.push_back(obs);
    }

    template<typename T>
    void notify(T value)
    {
        for (auto& o: _obs)
        {
            o->update(value, this);
        }
    }
};

template<typename T>
class B : public Observer<T>
{
    public:
    void update(T value, Subject* sub)
    {
        std::cout << "Value set = " << value << std::endl;
    }
};

template<typename T>
class A : public Subject
{
    T _x;
    public:
    void set(T value)
    {
        _x = value;
        notify(_x); // want to pass T without making Subject template
    }
};

int main() 
{
    A<int> a1;
    B <int> b1;

    a1.attach(&b1);
    a1.set(10);
}

CodePudding user response:

If you really promise that for notify<T>, there are only Observer<T>, then you could use a dynamic_cast safely:

class Subject;
class ObsBase{
    virtual ~ObsBase()=default;
};
template<typename T>
class Observer:public ObsBase
{
    public:
    virtual void update(T value, Subject *) = 0;
};

class Subject
{
    //If this is the owner, use std::unique_ptr<ObsBase>
    std::vector<ObsBase*> _obs;

    public:
    void attach(ObsBase* obs)
    {
        _obs.push_back(obs);
    }

    template<typename T>
    void notify(T value)
    {
        for (ObsBase* o: _obs)
        {
            auto* d = dynamic_cast<Observer<T>*>(o);
            if(d!=nullptr)
                d->update(value, this);
        }
    }
};
  • Related