Шаблон делегата полезен в некоторых случаях, как показал Марк.Проблема в том, что Apple использовала их гораздо больше, чем нужно.В частности, Apple попыталась (и с треском провалилась, imo) реализовать элементарный механизм event с использованием делегатов.
Это идет вразрез с целью шаблона делегата, который заключается в модульности поведение класса на компоненты.События не представляют поведение: они представляют (часто независимые) действия, которые происходят в зависимости от происходящего события (то есть действие 1008 * зависит от события, но эффекты могут быть в значительной степени независимыми от объекта, который вызвалсобытие).
Самая большая проблема в этом состоит в том, что у вас может быть только один обработчик делегата для события, в то время как в других языках есть много допустимых случаев, когда мы могли бы хотеть иметь несколько независимых потребителей события.Например, в C # оператор +=
используется для добавления обработчика события к событию объекта, что позволяет неограниченному количеству наблюдателей события.К сожалению, в Objective-C нет встроенного механизма событий, а также шаблон событий, используемый базовыми классами платформы Apple.
Использование делегатов для событий, по меньшей мере, ограничено.Кроме того, потребитель тесно связан с производителем, поскольку может существовать только один потребитель.Поэтому невозможно (ну, возможно, но было бы неразумно) для другого потребителя изменить делегата производителя.
Пример того, как Apple использует делегатов для того, что на самом деле events - это метод tableView:didSelectRowAtIndexPath
.Это событие.Почему должна быть разрешена зависимость только одной вещи от выбранной строки?«Решение» (хотя это скорее обходной путь) было бы для родителя, чтобы предоставить свой собственный делегат с его собственным методом делегата псевдо-события для его потомка.Но это просто означает больше работы и больше шансов на ошибку.
Примером того, как модель делегата правильно используется Apple (насколько это касается модели), является tableView:cellForRowAtIndexPath
метод.Этот метод позволяет потребителю выгружать и определять поведение tableView, и не имеет смысла предоставлять более одной его реализации.
One good В шаблоне делегата важно то, что он поддерживает как композицию, так и наследование.То есть вы можете получить класс контроллера, который реализует свои собственные методы-делегаты, которые затем можно создать, или вы можете просто создать свой класс, используя универсальный элемент управления, и сами предоставить методы-делегаты для этого элемента управления.
Однако,Я также не фанат передачи текущего (родительского) объекта в качестве делегата компонента (дочернего) объекта, так как это приводит к загрязнению несоответствия класса и концепции (весь класс теперь обеспечивает поведение только для одного из егокомпоненты в отличие от принадлежности к понятию самого класса).Лучший способ сделать это - предоставить специальный объект отображения, который реализует необходимые методы делегата.Однако, поскольку это не удобно в Objective-C, первый, к сожалению, чаще всего используется по соглашению.