Альтернативный шаблон проектирования для Observer для .Net

Первоначально я собирался реализовать шаблон наблюдателя в C# 3.0, чтобы решить свою проблему, хотя он не будет реализован точно таким же образом.

Моя проблема в том, что у меня есть веб-приложение с пользователями, которые могут отправлять сообщения. Уведомления поступают не напрямую другим пользователям, а в распределенный кэш, где объекты статистики обновляются, и пользователи могут проверять статистику и решать, хотят ли они обновлений или нет.

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

Я также просмотрел шаблон посредника, но я не думаю, что он подходит, потому что экземпляры посредника не будут иметь списка тех, кто в данный момент вошел в систему.

Теперь мне интересно, есть ли другой устоявшийся шаблон проектирования, который был бы более подходящим, или я должен просто доработать свой текущий шаблон Observer, чтобы он соответствовал моим потребностям.

Спасибо


person CountCet    schedule 28.07.2009    source источник
comment
Эта статья о msdn дала мне лучшее представление о том, что объясняют ответы ниже. msdn.microsoft.com/en-us/library/ms954621.aspx   -  person CountCet    schedule 28.07.2009


Ответы (3)


Разве вы не можете реализовать это через события/делегаты? Это стандартный способ реализации шаблона Observer в C# и других языках .Net.

person Oded    schedule 28.07.2009
comment
События могут быть самой ранней реализацией наблюдателя, но во многих отношениях они несовершенны. Худшее из них — отсутствие какого-либо хорошего механизма для работы со сроком действия подписки в случае отказа от издателя или подписчика [подписка должна стать недействительной, если отказались либо от издателя, либо от подписчика]. Другие шаблоны могут предоставить механизмы для облегчения этих проблем. - person supercat; 27.01.2013
comment
@supercat - В 2009 году не было реактивных расширений, не было Obeserver/Observable в BCL, и события были такими, если вы не хотели развертывать свои собственные. - person Oded; 27.01.2013
comment
@Oded: Достаточно справедливо, хотя перекатывание собственного было не слишком сложным. Я бы хотел, чтобы события с самого начала реализовывались с помощью метода подписки, возвращающего IDisposable. Не должно быть никакого специального типа «события»; подписка будет таким же методом, как и любой другой. Такой шаблон позволил бы классам легко разрешать асинхронную подписку на события (если делается попытка удалить объект в то время, когда издатель занят, он должен установить флаг в себе и в издателе событий, чтобы сказать, что это произошло ; тогда издатель может... - person supercat; 28.01.2013
comment
...очистить событие по своему усмотрению). Интересно, какие реальные преимущества дает наличие типа события как такового? - person supercat; 28.01.2013
comment
@supercat - У меня нет для тебя ответа. У дизайнеров и архитекторов .NET может быть ответ (хотя это может быть наследие VB6) - person Oded; 28.01.2013
comment
@Oded: я не знаю ничего, даже отдаленно напоминающего события .net в vb6. Насколько я помню, если бы у кого-то был Button с именем Foo, нажатие Foo привело бы к тому, что система выполнила бы метод Foo_Click, если бы он существовал (и ничего не сделала бы, если нет); если бы у кого-то был массив кнопок с именем Bar(), щелчок по любой из них вызывал бы Bar_Click с передачей дополнительного параметра, указывающего, какая кнопка. Я предполагаю, что во многом это связано с тем фактом, что делегаты и массивы были единственными квазиуниверсальными типами в ранних версиях .net; много уродства связано с первоначальным отсутствием дженериков. - person supercat; 28.01.2013

Разве события .Net не являются просто замаскированными паттернами-наблюдателями? :) У вас может быть класс, скажем, Statistic, и этот класс выставляет событие OnUpdate().

person cwap    schedule 28.07.2009
comment
Необходимость проверки делегата вашего события на ноль перед его вызовом кажется мне вынужденной оглядываться через плечо, чтобы убедиться, что кто-то наблюдает за вами. Что концептуально выглядит довольно странно. - person xyz; 28.07.2009
comment
Согласен, всегда ненавидел это :) - person cwap; 28.07.2009
comment
@ al7ut9ov8my4wopt5ur6ais5: Предоставление вспомогательному полю для делегата события того же имени, что и самому событию, было ИМХО серьезной ошибкой в ​​​​дизайне C #. Поддерживающему полю должно было быть присвоено другое имя, и попытка использовать имя события, например, вызов метода, должна была автоматически генерировать выполнение, если не нуль, иначе ничего не делать; попытка присвоить имя события null или сравнить его с null должна была воздействовать на поле выпечки. В противном случае имя события не должно считаться синонимом делегата. - person supercat; 28.01.2013

C# взял шаблон проектирования и сделал его первоклассным гражданином языка. Почему бы просто не использовать то, что есть? Я не вижу в вашем примере ничего, что нельзя было бы сделать со встроенной структурой событий в C#.

person Ed S.    schedule 28.07.2009
comment
Я не против использования событий, но я хочу избежать какой-либо двунаправленной зависимости между пользователем и классом, которая реализует обновление статистики. - person CountCet; 28.07.2009
comment
Нет никакой зависимости. Один класс выставляет событие, другой его обрабатывает. Шаблон уменьшает потребность в связи/зависимости между классами. - person Ed S.; 28.07.2009
comment
@EdS.: В правильном шаблоне наблюдателя издатель события не должен препятствовать сборке мусора подписчика (существуют ситуации, когда подписчик события может сделать что-то полезное без какой-либо ссылки на него; но сегодня, вероятно, лучше всего обрабатываются с помощью если подписчик использует ConditionalWeakTable, чтобы привязать свое время жизни к тому, что может о нем заботиться). События являются основным источником утечек памяти в .net. - person supercat; 28.01.2013
comment
@supercat: Да, я сам починил пару. Однако я не думаю, что это так уж распространено, поскольку большинство подписчиков переживают издателя. как и все, вы должны знать, что вы делаете. Ни одна абстракция не идеальна. Как вы сказали, слабая эталонная реализация предпочтительнее. - person Ed S.; 28.01.2013