Каким-то образом вы должны превратить контейнер в тему.
Основная проблема здесь - найти эффективный способ заметить изменения. В большинстве случаев, когда вы сталкиваетесь с этой проблемой, это , потому что вещь, которую вы хотите наблюдать, не предлагает эффективного механизма уведомления (возможно, потому что шаблон проектирования наблюдателя не был изобретен, когда они были написаны) .
[РЕДАКТИРОВАТЬ] Поскольку вы просите эффективный способ, общий ответ "это зависит". Шаблоны проектирования не имеют решения «один размер подходит всем». Это общие правила, как подходить к проблеме. То, как вам нужно реализовать правила в конкретной ситуации, - это то, что вы решаете, находясь в ситуации.
Как правило, если ваши наблюдатели должны идентифицировать небольшие изменения (например, изменение атрибута или добавление элемента), сообщение с уведомлением должно содержать достаточно информации, чтобы они могли сделать это эффективно. Поэтому, если у вас большой список и вставка, отправьте список и индекс нового элемента плюс «элемент как вставленный».
Что касается изменения атрибутов, есть два решения. Одним из них является добавление наблюдателя к каждому элементу в списке. Это может быть медленным и требовать много оперативной памяти, но это означает, что вы можете добавить несколько типов в один и тот же список.
Кроме того, у вас может быть «изменить элемент в списке». Это означает, что запрещено менять предметы напрямую, вы всегда должны пользоваться сервисом. Затем служба может работать как субъект и отправлять уведомления с элементом, старым и измененным значением и, возможно, с индексом в списке.
[EDIT2] Общее правило - собирать как можно больше информации об изменениях и передавать ее наблюдателям. Но это действительно зависит от вашей конкретной проблемы. Допустим, наблюдатель сидит на удаленной машине. В этом случае нет эффективного способа отправить ему весь список. Вы можете отправить только «элемент X был вставлен» и надеяться, что этого достаточно. Если у контейнера нет возможности замечать изменения (например, новые веб-страницы на веб-сайте), контейнер должен снова и снова пересматривать весь сайт, чтобы найти изменения, которые он затем может эффективно сообщить наблюдателям.
Опять же, детали действительно зависят от конкретной ситуации. Google запускает тысячи веб-пауков, которые посещают миллионы веб-страниц каждый час. Долгое время это было «эффективно» (как «единственным способом»). Некоторое время назад был реализован протокол "карта сайта", который позволяет администраторам превращать свои веб-сайты в темы, которые могут сообщать наблюдателю Google об изменениях.
Так что, если вы не можете привести более конкретный пример того, что вам нужно сделать, я не могу дать вам более конкретный ответ. В шаблонах проектирования есть момент, когда вам нужно сесть, принять реальную проблему и включить свой мозг.
[EDIT3] Вот несколько примеров использования шаблона наблюдателя:
Многие пользовательские интерфейсы используют этот шаблон для распространения событий среди заинтересованных сторон. В Qt у вас есть центральное место, где все субъекты могут регистрировать свои сигналы (уведомления, которые они будут отправлять) и где наблюдатели могут прикрепляться к объектам. Это означает, что есть единственное место, где все соединения управляются. Преимущество состоит в том, что вам не нужно добавлять эту структуру данных к каждому объекту. Кроме того, объекты извне (не-Qt объекты) могут отправлять и получать сообщения. Поскольку все в одном месте, эту структуру данных можно легко оптимизировать. Недостатком является то, что эта структура может стать очень большой, поэтому отправка сообщения займет больше времени, когда в нем участвует больше сторон (даже тех, которые совершенно не связаны).
Google использует протокол карты сайта для превращения веб-сайтов в темы, поскольку это гораздо эффективнее, чем обходить весь сайт снова и снова, даже если вы запрашиваете только время последнего изменения URL (HTTP HEAD вместо HTTP GET ).
Файловые системы в Windows и Linux предлагают уведомления, чтобы сообщить приложениям о новых или удаленных файлах. Основная проблема заключается в том, что должно происходить, когда файлы изменяются, когда приложение не запускается. Допустим, у вас есть приложение, которое поддерживает контрольные суммы файлов в каталоге. Очевидно, что вы хотели бы знать об изменениях, когда приложение не работало, но это означало бы, что служба уведомлений должна будет отслеживать последние отправленные изменения. Так что здесь, приложение должно прочитать все дерево при запуске, чтобы увидеть все, что оно могло пропустить, и оно должно использовать шаблон наблюдателя для изменений, происходящих во время работы.
Почтовый клиент является наблюдателем. Он сообщит почтовому серверу идентификатор последнего увиденного им письма, а сервер сообщит ему о любых новых письмах.
Когда у вас много изменений атрибутов в сложной модели, обычно это единственный способ централизовать все изменения (заставить их проходить через одно место) и прикрепить туда наблюдателей (вместо того, чтобы прикреплять N наблюдателей к M индивидууму). объекты). В этой реализации наблюдатели могут сказать «меня интересует любое изменение в любом месте» или «изменение поля X в любом предмете» или «любое изменение в предмете Y» (последнее обычно удваивается как «изменение поля» X в теме Y "- наблюдатель просто игнорирует изменения полей! = X).