Это плохая практика для делегата иметь ссылку на объект, для которого он является делегатом? - PullRequest
2 голосов
/ 22 октября 2009

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

Мой вопрос заключается в том, является ли плохой практикой для моего делегата ссылка на объект, для которого он является делегатом? Есть пара свойств этого объекта, к которым мне нужно иметь доступ независимо от того, какой делегат / стратегию я использую. Если это плохая форма, как мне получить доступ к свойствам?

Ответы [ 4 ]

9 голосов
/ 22 октября 2009

Не обязательно. Например, для объекта типа «контроллер» достаточно часто создавать объекты данных и представления и делать себя делегатом некоторых из этих объектов для правильного управления объектами.

3 голосов
/ 23 октября 2009

Это совсем не плохая практика. Шаблон делегата позволяет классу иметь общий способ общения с любым количеством объектов, если он реализует один и тот же протокол. Но класс, для которого вы устанавливаете делегат, также обычно будет иметь ряд открытых свойств или методов, которые позволяют вам запрашивать или изменять действия класса, в ответ на которые класс, в свою очередь, может инициировать несколько вызовов делегата. Таким образом, вам нужна ссылка на класс, которому вы являетесь делегатом, чтобы сказать объекту сделать что-то отличное от того, что уже есть, и, конечно, освободить его, когда вы закончите с ним!

По этой же причине важно всегда иметь какие-либо свойства делегата как назначать, а не сохранять свойства. Таким образом, когда исходный класс будет освобожден, он будет фактически освобожден, вместо того, чтобы иметь объекты-делегаты, которые он удерживает, вызывая цикл сохранения, который удерживает оба.

Это также, почему всякий раз, когда вы освобождаетесь, вы должны устанавливать ссылку на делегат на nil во всем, что может иметь набор ссылок на делегат. Таким образом, у класса не будет недопустимой ссылки на делегат, если делегат освобожден до того класса, который использует делегат.

2 голосов
/ 22 октября 2009

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

0 голосов
/ 22 октября 2009

Я бы сказал, да, это плохая практика. Идея, лежащая в основе делегата, состоит в том, что это фактически отдельный объект, который получает сообщения об объекте, для которого он является делегатом («делегатом»). Делегат должен иметь ссылку на делегата, а не наоборот, иначе это уже не настоящие отношения делегирования.

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

Этот способ также имеет то преимущество, что не предоставляет доступ к делегатору в методах, когда он вам действительно не нужен; например, ваш делегат может иметь метод didDoSomething, который не принимает аргументов, даже делегат, и просто используется для ведения журнала, а также метод delegator:(id)anObject didSomethingElse:(id)anotherObject, который вызывает некоторые свойства в делегаторе и гораздо более сложен.

Наконец, этот метод позволяет использовать один и тот же делегат для нескольких делегатов, поскольку вам не нужно обновлять свойство delegator для каждого объекта делегата.

Для хорошего примера того, как это работает, взгляните на документацию NSURLConnection , в частности, на методы делегатов - многие из них принимают форму connection:didDoSomething:, где первым аргументом является вызов соединения делегат. Разработчики обычно определяют один делегат соединения для нескольких соединений, реализуя свои методы делегата, чтобы делать разные вещи в зависимости от переданных в свойствах объекта NSURLConnection.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...