мы должны удалить наблюдателя при отмене регистрации? - PullRequest
1 голос
/ 31 мая 2011
Observer *o = New Observer();
Subject *s = new Subject() ;
s->register(o);

//Is it a good practice to delete the observer in the unregister function?
//I feel it is not. As the Observer object might still be in use,  for example , 
//it might be registered to another Subject. 
s->unregister(o);  

//So it is safe to rely on the client code to delete the object or rely on the smart pointer things
delete o;

Я хочу подтвердить правильность моего понимания относительно того, кто должен удалять объект наблюдателя.

Ответы [ 8 ]

5 голосов
/ 31 мая 2011

Я согласен с вашим наблюдением.Не рекомендуется удалять наблюдателя в функции отмены регистрации - по той простой причине, что «тот, кто создает ресурс, должен отвечать за удаление ресурса»

Это позволит избежать

  • Волшебное поведение, воспринимаемое создателем.
  • Поведение кода будет четко определено - тот, кто создает, должен удалить.Это заложит общую основу понимания разработки для новых разработчиков вашей системы.

Подобные темы обсуждаются в деталях во всех книгах с различной номенклатурой.

4 голосов
/ 31 мая 2011

Я бы сказал, используйте умные указатели, так как не нужно помнить, чтобы вызывать delete явно.

2 голосов
/ 31 мая 2011

Поскольку Subject не выделил Observer, он не должен пытаться освободить его. Это позволяет клиенту Subject управлять временем жизни и стратегией распределения Observer s любым способом, который он выберет (пользовательский распределитель, статически распределенная, автоматическая переменная). Это не заставляет клиента использовать new.

Очевидно, что ответственность за то, чтобы Observer не был уничтожен до того, как он был "незарегистрирован", по-прежнему лежит на клиентах.

1011 * Е.Г. *

Observer o;
Subject s;

s.register(&o); // could take a reference

// ...

s.unregister(&o);

// No potential for forgotten deletes
2 голосов
/ 31 мая 2011

С проектной точки зрения было бы излишним (хотя и не ошибочным) отменить регистрацию субъектов, если наблюдатель хорошо реализован.Опора на внешний код для обеспечения устойчивости поведения, если оно может быть применено, всегда может рассматриваться как плохой дизайн.

Что касается использования интеллектуальных указателей, если вам по какой-то причине требуется контроль над точкой уничтожения (закрытьфайлы в определенный момент времени, например, чтобы избежать проблем с доступом в последующем коде), тогда вы должны удалить явно, в противном случае гораздо удобнее полагаться на умные указатели.Вот почему существуют.

1 голос
/ 31 мая 2011

Это зависит от вашего дизайна. Я лично предпочитаю, чтобы удаление Обозревателя автоматически разъединяло его с субъектом, то есть отменяло регистрацию в деструкторе. Это избавляет от необходимости беспокоиться о снятии с учета, что потребует от вас наличия ссылок как на Субъекта, так и на Наблюдателя в точке уничтожения.

0 голосов
/ 06 октября 2013

Как правило, вам следует избегать побочных эффектов, таких как удаление указателя на объект в контейнере, если только контейнер не отвечает за создание указателя.

Проблемы указателей с шаблоном Observer запускаютнемного глубже, чем это.

Наблюдатель по своей природе имеет какую-то ссылку на Субъекта.Если эта ссылка является прямой ссылкой (например, не дескриптор), то, если этот объект выходит из области видимости или удаляется, когда наблюдатель выполняет вызов Notify (...), он генерирует исключение (или хуже).Таким образом, вы должны убедиться, что вы отсоединились (...) от наблюдателя при удалении субъекта.

Забыть это - проблема, поэтому мне нравится идея встроить ее в базовый класс виртуального деструктора.Это также означает, что Субъект имеет знания Обозревателя (ссылка на него), поэтому он может вызвать Detach (...).Что ставит вас в аналогичную ситуацию с Обозревателем (т.е. если он будет удален).Подход, который я нашел наиболее простым в использовании, заключается в том, чтобы Наблюдатель фактически являлся единичным объектом, в котором субъекты регистрировались для определенных уведомлений, а не просто «У меня есть состояние, которое вы хотите обновить».Это согласуется с пунктом 7 GoF, «Явное указание модификаций».Также, просто имеет смысл немного сузить поле обновлений.Это также позволяет подключать любую форму субъекта куда угодно.

Еще один случай, который необходимо рассмотреть, - это когда субъект удаляется во время итерации Notify (..).В вашем Observer у вас есть список субъектов, A, B и C. Вы меняете состояние и вызываете Notify (...) на A. A удаляет B. Теперь вы переходите к вызову Notify (...) на B, которого не существует.Если у вас есть это Detach (...) в деструкторе, B может больше не быть в списке.Но это может все же произойти, если вы решите перебирать копию Предметов, с которых вы начали, вместо фактического списка (был там, сделал это).По этой причине ваш наблюдатель должен обработать вызов Detach (...) во время итерации для уведомления (...).

У меня есть отработанный пример этого, опубликованный в блоге здесь .

0 голосов
/ 31 мая 2011

Другим аргументом против удаления является то, что объект Subject сообщает .

Удалив объект, ваш объект Subject стал владельцем объекта, поскольку он контролирует его время жизни. Поскольку в объект передается необработанный указатель, а не auto_ptr или unique_ptr, я бы предположил, как пользователь Subject, что он не становится владельцем объекта, не глядя на код. Поэтому я бы сказал, что интерфейс субъекта не сообщает, что он становится владельцем объекта. Таким образом, Субъект не должен удалять это, потому что кто-то еще (вероятно) имеет право собственности на него.

0 голосов
/ 31 мая 2011

Smartpointer или код клиента (не передавайте собственность, если это возможно) Если клиентский код создал объект, пусть тот же код уничтожит его:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...