I am currently trying to implement the Observer pattern in a little game, using this as reference. Though, I am trying to implement a solution to one of the problems exposed in the chapter : how to prevent the subject from sending a notification to a removed observer ?
Instead of having simple pointers or owning the observers in the subject class (with a vector of shared_ptrs, simple pointers, or anything that implies owning the object), I thought that it could be good to have weak_ptrs (knowing that the observers are already instantiated using make_shared and shared_ptr). The primary use of this to me would be to be able to check if the observer is still alive with weak_ptr.lock() and to remove it if it isn't, but is this a good practice ? Does this implies other problems ?
Here's my (stripped down) code :
Main method :
int main() {
shared_ptr<Game> game = std::make_shared<Game>(); //Game extends subject
shared_ptr<Renderer> renderer = std::make_shared<Renderer>(); //Renderer extends observer
game.addObserver(renderer); //Automatic cast from shared_ptr to weak_ptr
}
Subject class :
class Subject {
public:
virtual void removeObserverAt(int index) {
m_observers.erase(m_observers.begin() + index);
}
protected:
virtual void notify(int objectID, Event ev, int64_t timestamp) {
int i = 0;
for(std::weak_ptr<Observer> obs : m_observers) {
if(auto sobs = obs.lock()) {
sobs->onNotify(objectID, shared_from_this(), ev, timestamp);
} else {
removeObserverAt(i);
}
i++;
}
}
private:
std::vector<std::weak_ptr<Observer>> m_observers;
};
Observer class :
class Observer {
public:
virtual ~Observer() {}
virtual void onNotify(int objectID, std::weak_ptr<Subject> caller, Event ev) = 0;
private:
};