Objective-c асинхронная связь: цель / действие или шаблон делегирования? - PullRequest
14 голосов
/ 22 декабря 2009

Я имею дело с некоторыми асинхронными коммуникационными ситуациями (управляемый событиями анализ 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 аргументов.

Уведомления:

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

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

Я что-то упустил? что порекомендуете и почему?

Спасибо!

Ответы [ 3 ]

3 голосов
/ 22 декабря 2009

Вы упустили третий вариант - уведомления.

Вы можете попросить клиента получить уведомление от поставщика услуг о том, что у него есть новые данные. Когда клиент получает это уведомление, он может использовать данные поставщика услуг.

Это обеспечивает хорошую слабую связь; хотя некоторые решения сводятся к тому, хотите ли вы использовать систему push / pull.

0 голосов
/ 06 июля 2010

Еще один недостаток подхода делегации: Поставщик услуг может иметь только один делегат. Если ваш поставщик услуг - одиночный, и у вас есть несколько клиентов, этот шаблон не работает.

Это заставило меня перейти к действию / цели. Мой поставщик услуг удерживает состояние и используется несколькими клиентами.

0 голосов
/ 22 декабря 2009

Очень хороший вопрос.

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

if([delegate respondsToSelector:callback]){
    //call to callback here
}

Надеюсь, что поможет взвесить варианты

...