I try to design Handle, Event Handler pattern. So when specific event happens, I obtain appropriate Handle, and pass it to Event Handler in order to do processing. I wondered about different approaches:
low level approach: making association between enums with event handlers and then pass pointer to handle to appropriate event handler
Visitator design pattern: low scalability
Observer design pattern. Handles are subjects (publishers), Event Handles are observers.
I chose Observer design pattern. However, during implementations I encountered problems connected with cyclic dependencies:
Firstly I have to mention that I have following assumptions:
- Interface and implementation must be in header file
- Event handler must have a pointer to Handler in order to get from it some data.
In order to make completely transparent usage of Observer Pattern I implemented it in this way:
Subject.h:
#include <vector>
#include "Observer.h"
class Observer;
class Subject {
public:
virtual ~Subject() {}
void add(Observer* o) {
obs_.push_back(o);
}
void notify() {
for(Observer* o : obs_)
o->update(this);
}
private:
std::vector<Observer*> obs_;
};
Observer.h:
#include "Subject.h"
class Subject;
class Observer {
public:
virtual ~Observer() {}
virtual void update(Subject *subject) = 0;
};
Handle.h
#include "Subject.h"
#include "EventHandler.h"
class EventHandler;
/*Handle identifies I/O resources*/
class Handle : public Subject {
public:
Handle() {}
virtual ~Handle() {}
//should queue events internally
virtual int handle() = 0;
void addEventHandler(EventHandler *event_handler) {
add(event_handler);
}
void handleMe() {
notify();
}
};
EventHandler.h
#include "Observer.h"
#include "Subject.h"
#include "Handle.h"
/*
* The set of operations available to process events
* that occur on handles
*/
class Subject;
class Handle;
class EventHandler : public Observer {
public:
EventHandler() {}
virtual ~EventHandler() {}
//hook method dispatched by a Reactor
//to handle events
virtual int handle_event(
Handle *handle) = 0;
private:
virtual void update(
Subject *subject) override {
Handle *handle = dynamic_cast<Handle*>(subject);
if(handle == nullptr)
throw std::bad_cast();
handle_event(handle);
}
};
However during compilation I obtained an error:
error: cannot dynamic_cast 'subject' (of type 'class Subject*')
to type 'class Handle*' (target is not pointer or reference to complete type)
However, when in Observer and Event Handler classes I change Subject* into void* parameter in updatemethod eveything works fine. But void* is something what I want to omit. Can I do it better?
Thank You for any suggestions.
Aucun commentaire:
Enregistrer un commentaire