Я столкнулся с интересной проблемой при реализации шаблона Observer с C++ и STL. Рассмотрим этот классический пример:Проблемы с реализацией шаблона «Наблюдатель»
class Observer {
public:
virtual void notify() = 0;
};
class Subject {
public:
void addObserver(Observer*);
void remObserver(Observer*);
private:
void notifyAll();
};
void Subject::notifyAll() {
for (all registered observers) { observer->notify(); }
}
Этот пример можно найти в каждой книге по шаблонам проектирования. К сожалению, системы реальной жизни более сложны, поэтому вот первая проблема: некоторые наблюдатели решают добавить других наблюдателей к Субъекту при уведомлении. Это аннулирует цикл «for» и все итераторы, которые я использую. Решение довольно простое - я делаю снимок зарегистрированного списка наблюдателей и перебираю снимок. Добавление новых наблюдателей не отменяет моментальный снимок, поэтому все выглядит нормально. Но здесь возникает другая проблема: наблюдатели решают уничтожить себя при уведомлении. Хуже того, один наблюдатель может решить уничтожить всех других наблюдателей (они контролируются из сценариев), что делает недействительными как очередь, так и моментальный снимок. Я нахожусь итерацией по выделенным указателям.
Мой вопрос: как я должен справляться с ситуациями, когда наблюдатели убивают друг друга? Есть ли готовые к использованию шаблоны? Я всегда думал, что «Наблюдатель» - самый простой образец дизайна в мире, но теперь кажется, что его не так просто реализовать правильно ...
Спасибо вам всем за ваш интерес. Сводка решений:
[1] «Не делай этого» Извините, но это обязательно. Наблюдатели контролируются из сценариев и собираются с мусором. Я не могу контролировать сбор мусора, чтобы предотвратить их де-распределение;
[2] «Использовать boost :: signal» Самое многообещающее решение, но я не могу повысить эффективность проекта, такие решения должны принимать только руководитель проекта (мы пишем в Playstation);
[3] "Использовать shared__ptr" Это предотвратит отказ наблюдателей от выделения. Некоторые подсистемы могут полагаться на очистку пула памяти, поэтому я не думаю, что могу использовать shared_ptr.
[4] «Отложить освобождение наблюдателя» Наблюдатели очереди для удаления во время уведомления, а затем использовать второй цикл для их удаления. К сожалению, я не могу предотвратить освобождение, поэтому я использую трюк оберточного наблюдателя с каким-то «адаптером», сохраняя фактически список «адаптеров». На деструкторе наблюдатели отстраняются от своих адаптеров, затем я беру свой второй цикл, чтобы уничтожить пустые адаптеры.
p.s. это нормально, что я редактирую свой вопрос, чтобы подвести итог всему сообщению? Я noob на StackOverflow ...
Хороший вопрос! Я не рассматривал использование шаблона наблюдателя, где наблюдателям разрешено создавать и уничтожать других наблюдателей субъекта. –
Мне нравится суммировать ответы на вопрос в вопросе, просто не изменяйте исходный вопрос с удалением, или позже читатели могут пропустить нюансы исходного вопроса (не то, что вы сделали, я думаю, что ваше подведение итогов и замечание о том, что его обобщенный). – Jay
Вы когда-нибудь испытывали какие-либо из них, чтобы увидеть, какой из них вам понравился, лучше всего или лучше всего работал? – prolink007