samedi 6 mars 2021

How to make observer understand different data from publishers?

I've tried to implement my own observer pattern and I faced a problem: I want to have an observer that can receive various datatype update information from several publishers, but I don't know how to make the observer understand what type of event information it receives.

I tried to achieve it this way:

template<typename TData>
class Event 
{
    public:
        TData data; // Data from publisher to observer
        Event(TData data) : data(data) { }
}; 



class IObserver
{
    public:
        template<typename TEvent>
        void Update(TEvent* e) {}
};


class IPublisher
{
    protected:
        std::list<IObserver*> observers;    

    public:

        void AddObserver(IObserver* o)
        {
            observers.push_back(o);
        }

        void DeleteObserver(IObserver* o) 
        {
            observers.remove(o);
        }

        virtual void Notify() = 0;
};

but quickly found out that it doesn't work when I tried to derive specific classes

class Sky : public IPublisher
{

    public:
        enum SkyEventType
        {
            NOTHING,
            ECLIPSE,
            STARFALL,
            PLANET_PARADE,
        };

        void Notify() override
        {
            Event<SkyEventType> e(st);
            for(auto it = observers.begin(); it != observers.end(); ++it)
            {
                (*it)->Update(&e);
            }
        }

        void DoEclipse()
        {
            st = SkyEventType::ECLIPSE;
            Notify();
        }

        void DoNothing()
        {
            st = SkyEventType::NOTHING;
            Notify();
        }

    private:

        SkyEventType st = SkyEventType::NOTHING;
};

class Wheather : public IPublisher
{
    public:

        enum WheatherEventType
        {
           CLEAR,
           RAINY,
           CLOUDY,
        };
        void Notify() override 
        {
            Event<WheatherEventType> e(wt);
            for(auto it = observers.begin(); it != observers.end(); ++it)
            {
                (*it)->Update(&e);
            }
        }

        void DoClear()
        {
            wt = WheatherEventType::CLEAR;
        }

        void DoRain()
        {
            wt = WheatherEventType::RAINY;
        }

        void DoClouds()
        {
            wt = WheatherEventType::CLOUDY;
        }

    private:
        WheatherEventType wt = WheatherEventType::CLEAR;
};

class Astronomer : public IObserver
{
    public:
    //Update method should change this fields
    Sky::SkyEventType skyEvent = Sky::SkyEventType::NOTHING; 
    Wheather::WheatherEventType wheatherEvent = Wheather::WheatherEventType::CLEAR;




        /*
          I got stuck implementing an Update method 
          and understand that I do wrong.

       */

};

What should I do to make observer understand different data?

Aucun commentaire:

Enregistrer un commentaire