implementation design pattern Observer/Observable

implementation design pattern Observer/Observable - C++ - Programmation

Marsh Posté le 02-05-2008 à 12:32:29    

Bonjour à tous,
 
J'ai un problème pour implémenter le design pattern observer/observable en C++: le truc c'est qu'un observable doit connaitre les observers qui l'observent (ca permet notamment de notifier une modification d'état à tous les observers) mais je pense qu'il faut également que l'observer connaisse les observables qu'il observe puisque s'il est détruit, il faut qu'il se désenregistre auprès de ses observables (je sais pas si je suis très clair).
Voici mon code:
Observable.h:

Code :
  1. #include <set>
  2. template<typename Subject> class Observer;
  3. template<typename Subject>
  4. class Observable   
  5. {
  6. private:
  7. std::set<Observer<Subject>*> _setObservers;
  8. public:
  9. Observable();
  10. ~Observable();
  11. void addObserver(Observer<Subject> *o);
  12. void deleteObserver(Observer<Subject> *o);
  13. void notifyObservers(void* arg=0);
  14. };


 
Observer.h :

Code :
  1. #include <set>
  2. template<typename Subject> class Observable;
  3. template<typename Subject>
  4. class  Observer
  5. {
  6. private:
  7. std::set<Observable<Subject>*> _setObservables; /*!< La liste des objets a observer */
  8. friend Observable<Subject>;
  9. public:
  10. virtual ~Observer();
  11. virtual void update(Observable<Subject> *s, void* arg=0) = 0;
  12. };


 
Observable.cpp :

Code :
  1. #include "Exception.h"
  2. template<typename Subject>
  3. Observable<Subject>::Observable()
  4. {}
  5. template<typename Subject>
  6. Observable<Subject>::~Observable()
  7. {
  8. std::set<Observer<Subject>*>::iterator itObs;
  9. for (itObs=_setObservers.begin(); itObs!=_setObservers.end(); ++itObs)
  10.  (*itObs)->_setObservables.erase(this);
  11. }
  12. template<typename Subject>
  13. void Observable<Subject>::addObserver(Observer<Subject> *o)
  14. {
  15. if (o == 0)
  16. {
  17.  NullPointerException e;
  18.  throw e;
  19. }
  20. _setObservers.insert(o);
  21. o->_setObservables.insert(this);
  22. }
  23. template<typename Subject>
  24. void Observable<Subject>::deleteObserver(Observer<Subject> *o)
  25. {
  26. using namespace std;
  27. if (o == 0)
  28. {
  29.  NullPointerException e;
  30.  throw e;
  31. }
  32. o->_setObservables.erase(this);
  33. _setObservers.erase(o);
  34. }
  35. template<typename Subject>
  36. void Observable<Subject>::notifyObservers(void* arg)
  37. {
  38. std::set<Observer<Subject>*>::iterator it;
  39. for (it=_setObservers.begin(); it!=_setObservers.end(); ++it)
  40.  (*it)->update(this, arg);
  41. }


 
et Observer.cpp :  

Code :
  1. #include "Observable.h"
  2. template<typename Subject>
  3. Observer<Subject>::~Observer ()
  4. {
  5. std::set<Observable<Subject>*>::iterator itObs;
  6. itObs = _setObservables.begin();
  7. while (itObs!=_setObservables.end())
  8. {
  9.  (*itObs)->deleteObserver(this);
  10.  itObs = _setObservables.begin();
  11. }
  12. }


 
Le problème de mon approche est d'utiliser les friend mais je vois pas comment faire autrement puisque je ne veux pas mettre d'accesseur à mon _setObservables dans ma classe observer (ça na pas de sens que l'utilisateur de ma classe sache comment je gère les observables dans observer). De même, je ne voudrais pas avoir à ajouter de méthodes addObservable et deleteObservable dans ma classe Observer. Donc je me demande si je suis pas dans les 0.0005% des cas où on peut utiliser les friend?


Message édité par Polo37 le 02-05-2008 à 15:32:18
Reply

Marsh Posté le 02-05-2008 à 12:32:29   

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed