Я пытаюсь переписать нашу реализацию Observer / Observable, чтобы использовать std :: shared_ptr / std :: weak_ptr, чтобы избавиться от некоторых неприятных состояний гонки, присутствующих в коде.
Как правило, регистры-наблюдатели регистрируютсясами, когда выполняется какое-то условие или когда они конструируют дочерние объекты, например, так:
// Used to be raw 'this' now child instead derives a weak_ptr and stores it
child->addObserver(shared_from_this())
И отменяет регистрацию в деструкторе, например:
child->removeObserver(this); // Not shared_from_this() since in destructor
В некоторых ситуациях это работает нормально, однаково многих случаях наблюдатель хочет зарегистрировать себя в конструкторе.Поскольку shared_ptr еще не создан, мы не можем вызывать shared_from_this ().
Поскольку для реализации шаблона наблюдателя в C ++ обычно рекомендуется weak_ptr, мне интересно, каков идиоматический способ решения вышеуказанной проблемы.
Некоторые мысли:
- Пусть фабрика, которая создает объект-наблюдатель, регистрирует наблюдателя.Это приводит к утечке абстракций у наблюдателя (почему фабрика должна знать, кого хочет наблюдать ребенок?) И вынуждает наблюдателя выставлять внутренние объекты, которые он может захотеть наблюдать
- Добавить метод init, который вызывается фабрикой после конструкторазавершено, лучше, чем выше, но какова семантическая разница между конструктором и init в любом случае?Что должно быть сделано где?Это даже RAII?Действительно, некоторые языки даже называют свои конструкторы init.
- Передать лямбду в конструктор, который принимает другую лямбду, которая вызывается после построения
- Может быть, какая-то магия шаблона?
- Реализовать шаблон наблюдателя другим способом.