Objective-c асинхронная связь: целевое/действие или шаблон делегирования?
Я имею дело с некоторыми асинхронными ситуациями связи (управляемый событиями парсинг XML, обработка ответа NSURLConnection и т.д.). Я попытаюсь кратко объяснить свою проблему:
В моем текущем сценарии есть поставщик услуг (который может разговаривать с парсером xml или выполнять некоторую сетевую связь) и клиент, который может попросить поставщика услуг выполнить некоторые из своих задач асинхронно. В этом случае, когда поставщик услуг завершает свою обработку, он должен передать результаты клиенту.
Я пытаюсь найти какой-то шаблон или эмпирическое правило для реализации подобных вещей, и я вижу 3 возможных решения:
1. Используйте шаблон делегирования: клиент является делегатом поставщика услуг, и он получит результаты после завершения задачи.
2. Используйте подход "цель/действие" . Клиент просит поставщика услуг выполнить задачу и передать селектор, который должен быть вызван поставщиком услуг после его завершения.
3. Использовать уведомления.
(Обновление). Через некоторое время, пытаясь решить проблему №2 (цель и действия), я пришел к выводу, что в моем случае лучше использовать подход делегирования (№ 1). Вот плюсы и минусы каждого варианта, как я их вижу:
Делегирование:
-
1 (+) Потенциал варианта 1 заключается в том, что мы можем проверить ошибки времени компиляции, потому что клиент должен реализовать протокол делегирования поставщика услуг.
-
1 (-) Это также является недостатком, поскольку он заставляет клиента быть тесно связанным с поставщиком услуг, поскольку он должен реализовать свой протокол делегирования.
-
1 (+) Это позволяет программисту легко просматривать код и находить, какой метод клиента, поставщик услуг вызывает, чтобы передать его результаты.
-
1 (-) С точки зрения клиента, не так просто найти, какой метод будет вызываться поставщиком услуг после его получения. Это все еще легко, просто перейдите к методам протокола делегата и это, но подход №2 более прямой.
-
1 (-) Нам нужно написать еще код: определить протокол делегата и реализовать его.
-
1 (-) Также необходимо использовать шаблон делегирования для делегирования поведения. Этот сценарий не будет точным случаем делегирования, семантически.
Действие/Целевой подход
-
2 (+) Верхняя часть опции 2 заключается в том, что при вызове метода поставщика услуг должен быть указан параметр @selector, определяющий действие обратного вызова, поэтому программист знает правду там какой метод будет вызван для обработки результатов.
-
2 (-) В отличие от этого трудно найти, какой метод будет вызываться на клиенте во время просмотра кода поставщика услуг. Программист должен перейти к вызову службы и увидеть, какой @selector передается вместе.
-
2 (+) Это более динамичное решение и вызывает меньшую связь между частями.
-
2 (-) Возможно, одна из самых важных вещей: Она может вызывать ошибки во время выполнения и побочные эффекты, так как клиент может передать селектор который не существует для поставщика услуг.
-
2 (-) Использование простого и стандартного подхода (#performSelector: withArgument: withArgument:) поставщик услуг может передавать только до 2 аргументов.
Уведомления:
- Я бы не выбрал уведомления, потому что я думаю, что они должны использоваться, когда нужно обновлять более одного объекта. Кроме того, в этой ситуации я хотел бы прямо указать объект-делегат/целевой объект, что делать после создания результатов.
Заключение. На этом этапе я бы выбрал механизм делегирования. Такой подход обеспечивает большую безопасность и позволяет легко просматривать код, чтобы отслеживать последствия отправки делегату результатов действий поставщика услуг. Отрицательные аспекты этого решения заключаются в том, что: это более статическое решение, нам нужно написать больше кода (связанный с протоколом), и, семантически говоря, мы не говорим о делегировании, потому что поставщик услуг не будет делегировать что-либо.
Я что-то упустил? что вы рекомендуете и почему?
Спасибо!
Ответы
Ответ 1
Вы пропустили третий вариант - уведомления.
Вы могли бы наблюдать за клиентом за уведомлением поставщика услуг, указав, что у него есть новые данные. Когда клиент получает это уведомление, он может использовать данные у поставщика услуг.
Это позволяет легко расцепляться; некоторые из решений сводятся к тому, хотите ли вы систему push/pull.
Ответ 2
Очень хороший вопрос.
Я не думаю, что я квалифицирован, но пока (как я новичок), чтобы прокомментировать, какой шаблон дизайна лучше, чем другой. Но просто хотел упомянуть, что недостаток, о котором вы упоминали в пункте 2 (исключение во время выполнения), можно избежать с помощью
if([delegate respondsToSelector:callback]){
//call to callback here
}
Надеюсь, что это поможет взвесить варианты.
Ответ 3
Еще один недостаток подхода Делегации:
У поставщика услуг может быть только один делегат. Если ваш поставщик услуг является одиночным, и у вас несколько клиентов, этот шаблон не работает.
Это заставило меня пойти на подход Action/Target. Мой поставщик услуг имеет состояние и распределяется между несколькими клиентами.