Які переваги схеми делегата перед схемою спостерігача?


9

У шаблоні делегування лише один об'єкт може безпосередньо слухати події іншого об'єкта. У шаблоні спостерігача будь-яка кількість об'єктів може слухати події конкретного об'єкта. Розробляючи клас, який повинен сповіщати інші об'єкти (и) про події, навіщо ви коли-небудь використовувати шаблон делегата над шаблоном спостерігача? Я бачу модель спостерігача як більш гнучку. Зараз у вас може бути лише один спостерігач, але для майбутнього проекту може знадобитися кілька спостерігачів.


4
Що ви маєте на увазі під "делегатним шаблоном"? Якщо ви говорите про щось на зразок делегатів .net, у вас може бути стільки передплатників.
CodesInChaos

Пов’язане, хоч і більше зосереджене на Cocoa: NSNotificationCenter vs делегування (використовуючи протоколи)?
mouviciel

Відповіді:


7

Сам по собі модель делегата не існує. Я припускаю, що ви маєте на увазі модель делегації .

Як я розумію, вони є повним зворотом один одного і використовуються для різних цілей.

Як правило, за схемою спостерігача будь-яка кількість об'єктів спостерігачів прослухає подію на другому об'єкті та діятиме події. Другий об’єкт не має знань про своїх слухачів. Це просто кличе до них.

Об'єкт делегата передається другому об'єкту, який викликає методи безпосередньо на делегаті. І в цьому полягає перевага, яку ви шукаєте. Замість того, щоб надсилати одне повідомлення декільком слухачам, він має повний контроль над одним об’єктом (в даний момент часу). Див. Також Інверсія управління .


6

Ви дивитесь на речі неправильно. Спостерігач бачить, що відбувається певна подія. Це не впливає на нього чи володіє ним. Делегат обробляє певну подію та має право власності на обробник, навіть якщо делегатору належить інтерфейс події.


1
Делегат насправді є не що інше, як спостерігач за подією. Делегату нічого не потрібно "обробляти". Він може спокійно нічого не робити і не впливатиме (або принаймні не повинен) впливати на екземпляр, який викликав подію.
Мар'ян Венема

5
@MarjanVenema - якщо об'єкт А чи не делегуючи відповідальність за події на об'єкт B, ви не використовуєте шаблон делегування: ви використовуєте шаблон спостерігача тільки з одним спостерігачем.
Теластин

Так, саме про це я і думав. Я розумів, що делеговані - це типи підписів події, які використовуються підписником події "На будь-якому". Очевидно, що делегати в C # не є одноплатними, як, наприклад, Delphi.
Мар'ян Венема

@Marjan Venema "Делегат насправді - це не що інше, як спостерігач за подією". - це залежить, якою мовою ви говорите. У Цілі C деякі делегати відповідають за надання даних - наприклад, делегатів даних - і об'єкт, у якого відсутній делегат даних, не має даних. У цих випадках відбувається делегування, відмінне від акта просто спостерігати за чимось.
окулус

1
@occulus: дякую за роз’яснення. Шкода, що мови не можуть погодитись з термінологією ... Якщо говорити про програмування в мовному агностиці, стає трохи важко, коли люди розуміють різні речі за одними і тими ж словами.
Мар'ян Венема

4

Це питання кількох компромісів.

Компроміси:

  • гнучкість (з точки зору наявності n> 1 делегатів / спостерігачів)
  • вартість відправки повідомлення
  • стійкість (здатність підтримувати недоступність делегата / спостерігачів)
  • простота використання

Делегат:

  • не дуже гнучка - додавання більше ніж одного делегата неможливе (передбачає певну форму "мультиделегата", тобто модель спостерігача)
  • надіслати повідомлення дешево, O (1) - така ж вартість, як і дзвінок на будь-яку іншу функцію чи метод (не потрібно шукати, черги повідомлень чи іншої інфраструктури)
  • зазвичай не є стійкими - очікується, що делегати будуть присутні і виконують свою частину роботи, тобто відправник прагне відмовити, якщо не відомий делегат
  • легко зрозуміти, легко здійснити

Шаблон спостерігача:

  • дуже гнучка - дизайн додає n> 1 спостерігачів
  • відправлення повідомлення має вартість, що має на увазі кількість спостерігачів, O (n), тобто n спостерігачів потребують n часу та повідомлень (принаймні, в наївній реалізації)
  • зазвичай пружні - від спостерігачів, як правило, не очікується виконати будь-яку роботу від відправника. Це навіть якщо немає спостерігача, відправник не впливає
  • може стати досить складним для розуміння, зокрема, від спостерігачів очікується реакція на повідомлення (чи має значення порядок ?, який спостерігач реагує в який спосіб?)

1

Як я вас розумію, делегатний шаблон є механізмом обробника подій іншими мовами, наприклад, Delphi. Таким чином, це просто реалізація структури спостерігача з великим обмеженням: одночасно лише один слухач.

Недолік обробників подій або делегатів очевидний: лише один спостерігач.

Перевага не така очевидна: продуктивність. За допомогою шаблону спостерігачів ви можете додати багато спостерігачів. Якщо трапляється подія, про яку потрібно повідомити спостерігачів, вам потрібно буде перерахувати спостерігачів і надіслати повідомлення кожному. Це може швидко забруднити будь-який спостерігається екземпляр, особливо коли кількість подій, які потребують сповіщення, також значна.


Так? Делегат C # - це лише підпис методу як типу змінної (еквівалентний, наприклад, int (*my_int_f)(int)в C). Я завжди думав, що вони зробили б це простіше зрозуміти, зробивши його більш схожим на struct / enum. Подія - це гачок для гнучких масивів слухачів, використовуючи єдиний підпис делегата. Ви могли б зробити це без події (саме тому я припускаю, що ОП означала модель делегування, що дуже відрізняється), але мова полегшує вам.
pdr

хм. Не так добре в курсі C #. Я розумів, що делегати є еквівалентом типів підписів подій, які використовуються подіями "OnWever", наприклад, Delphi. Тож на C # події можна підписатись декількома слухачами?
Мар'ян Венема

Родова Дія <T> є делегатом. Це не має нічого спільного з подіями, це змінна, яку передають навколо. І так, кілька слухачів можуть прослухати одну подію.
pdr

ок, дякую, сподіваюсь, я можу це зробити прямо ... :-) Отримав посилання на C # і зосередився більше на механізмі подій.
Мар'ян Венема

1

Це стара публікація, але я все одно передзвоню, тому що інші відповіді не стосуються того, що відбувається при використанні будь-якого зразка, вони, здається, більше стосуються теорії, ніж практики.

Як працюють делегація та спостерігач

За допомогою делегації делегатор визначає саме того, хто буде реагувати на певну подію в момент створення джерела потенційної події. Ви можете подумати про цього слухача як про одного спостерігача . У випадку шаблону спостерігача спостерігач вибирає того, кого він спостерігає, коли йому здається, що він любить; тому залежності залежно від спостереження проти делегування. З оглядовим малюнком вважайте газету та передплатників як спостерігачів. Спостерігачі контролюють, коли стосунки будуть створені. З делегацією подумайте працівника та роботодавця. Роботодавець контролює, коли створюються відносини та хто саме відповідає за конкретні події. Співробітники не можуть вибрати, над якими завданнями вони працюють ... загалом.

Деяка аргументація делегації може мати одного спостерігача, але я думаю, що реальна різниця між ними полягає в тому, як призначається обробка подій. Ви ніколи не побачите реєстру делегатів події. Він ніколи не дізнається, що навіть керує подією, поки це не відбудеться, і делегатор не зателефонує на публічний метод.

Перевага делегації

Ця модель є дуже жорсткою, і більшість звичайних конструкцій є більш простими і, як правило, більш надійними. Це змушує вас оголосити обробника події вперед на момент ініціалізації джерела потенційної події. Якщо вам потрібен хтось, щоб керувати трафіком, ви призначаєте директора дорожнього руху, перш ніж відкривати вулицю. Що стосується спостерігача, то ви дозволяєте дорожньому поліцейському обирати, коли направляти рух в будь-який час, коли він чи вона відчує це.

Недоліки делегації

Недоліком цієї конструкції є те, що вона не є гнучкою. Якщо ви реалізовували якийсь код для передплати газети, газета / делегатор повинні були б точно визначити, хто може читати новини, вдруге вони створені. За шаблоном спостерігачів вони можуть бути зареєстровані пізніше в будь-який час, і в газеті потрібно буде лише знати, що підписалася нова особа.

Коли вибрати делегацію?

Коли вам потрібні один конкретний спостерігач (і), і немає жодних підстав для того, щоб змінити того, хто спостерігає, то жорсткий дизайн структури делегування буде корисним.

Наприклад, вам потрібен клас / об'єкт для обробки спливаючого вікна для певної помилки. Існує не так багато причин, чому під час запуску вам потрібно буде переключити, хто обробляє конкретну помилку, тому делегування помилки "поза пам'яттю" одному об'єкту було б сенсом. Створення масиву потенційних обробників, а потім реєстрація цих обробників для помилки "Поза пам'яті" не мала б особливого сенсу; це може бути прикладом використання шаблону спостерігачів у цій ситуації. Під час запуску ви можете змінити, які методи викликаються або що викликається "делегатом" для змінних подій, але замінити обробник подій на конкретну подію під час виконання не є звичайним.

Не можливо неможливо замінити делегатів, як ви робили за схемою спостерігачів, її просто складно. У реальному світі, можливо, ви хочете поміняти дорожні служби, щоб новий делегатор обробляв трафік. Можна стверджувати, що кращий дизайн зробив би оригінальним делегатом міліцію, а не одного міліціонера, але я відхилився ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.