--- /dev/null
+#ifndef MSP_GAME_EVENTOBSERVER_H_
+#define MSP_GAME_EVENTOBSERVER_H_
+
+#include <msp/core/algorithm.h>
+#include <msp/core/noncopyable.h>
+#include "eventbus.h"
+
+namespace Msp::Game {
+
+class EventSourceBase;
+
+class EventObserver: public NonCopyable
+{
+private:
+ EventBus &bus;
+ std::vector<EventSourceBase *> observed_sources;
+
+public:
+ EventObserver(EventBus &);
+ ~EventObserver();
+
+ template<typename T>
+ void observe(std::function<void(const T &)> cb)
+ { bus.add_observer<T>(*this, std::move(cb)); }
+
+ template<typename T, typename S>
+ void observe(S &, std::function<void(const T &)> );
+
+ void remove_source(EventSourceBase &);
+};
+
+template<typename T, typename S>
+void EventObserver::observe(S &src, std::function<void(const T &)> cb)
+{
+ src.add_observer(*this, std::move(cb));
+ auto i = lower_bound(observed_sources, &src);
+ if(i==observed_sources.end() || *i!=&src)
+ observed_sources.insert(i, &src);
+}
+
+} // namespace Msp::Game
+
+#endif