Bonjour à tous,
Voilà un problème courant lorsque l'on implémente le pattern Observer. L'observable détient une liste d'écouteurs, il la parcours pour notifier un événement et un écouteur en réception de cet événement n'a plus besoin d'écouter. Il se retire alors de la liste ce qui provoque l'invalidation de l'itérateur toujours en cours d'itération.
Un petit exemple pour être plus concret :
Je ne sais pas si ce code compile, en tout cas il est pas propre mais c'est juste pour étayer le principe.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 class IListener { friend class Observable; protected: virtual void OnEvent() = 0; } class Observable { public: void AddListener(IListener* pListener) { m_vecListeners.push_back(pListener); } void RemoveListener(IListener* pListener) { m_vecListeners.erase(std::remove(m_vecListeners.begin(), m_vecListeners.end(), pListener), m_vecListeners.end()); } private: void NotifyEvent() { for(std::vector<IListener*>::iterator it = m_vecListeners.begin(); it != m_vecListeners.end(); ++it) (*it)->OnEvent(); } std::vector<IListener*> m_vecListeners; }; class Ecouteur : public IListener { public: Ecouteur() { m_observable.AddListener(this); } protected: virtual void OnEvent() { m_observable.RemoveListener(this); } private: Observable m_observable; };
Du coup là quand l'observable émet un événement, ça crash. Il y a des solutions mais qui contraignent à ce que l'écouteur doive connaître la gestion des événements de l'écouté pour l'utiliser d'une manière particulière, et ça c'est pas normal.
Alors comment faire proprement ?
Merci
Partager