Что такое пересылка в ООП и чем она отличается от делегирования? - PullRequest
19 голосов
/ 19 октября 2011

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

Ответы [ 3 ]

11 голосов
/ 16 февраля 2015

Давайте сначала определим два термина:

  • отправитель : the object that sends a message/task to another object(the receiver)
  • получатель : the object that receives a message/task from the sender

Разница между пересылкой и делегированием заключается в том, что при пересылке the receiver acts in its own context, тогда как при делегировании the receiver acts on the behalf of the sender.

Вот отличная метафора из этого сообщения в блоге :

Делегирование и пересылка очень похожи.Одна метафора, которая может помочь отличить их, - это думать о получении электронного письма с просьбой пожертвовать немного денег на достойную благотворительность.

  • Если вы перешлите электронное письмо другу идруг жертвует деньги, друг жертвует свои собственные деньги и получает собственную налоговую квитанцию.
  • Если вы делегат отвечая вашему бухгалтеру, бухгалтер пожертвует ваши деньги на благотворительность и вы получите налоговую квитанцию.
10 голосов
/ 19 октября 2011

Пересылка - это что-то вроде «наследования через сдерживание» или «наследование реализации трудным путем».

Типичное наследование реализации:

class Base
{
 public:
    void baseFn() { }
};

class Derived : public Base
{
 public:
    void derivedFn() { }
};

Теперь экземпляр Derived имеетметод baseFn ().Это способ совместного использования реализации между различными классами.

Пересылка выглядит следующим образом:

class Contained
{
 public:
    void containedFn() { }
};

class Thing
{
 public:
    void thingFn() { }
    void containedFn() { mContained.containedFn(); }
 private:
    Contained mContained;
};

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

Делегирование являетсяособый случай пересылки, где в «вещи для пересылки» находится сам интерфейс.

class Delegate
{
 public:
    virtual void doDelegateAction() = 0;
};

class DelegateA : public Delegate
{
    virtual void doDelegateAction() { }
};

class DelegateB : public Delegate
{
    virtual void doDelegateAction() { }
};

class Thing
{
 public:
    void Thing (Delegate * delegate) { mDelegate = delegate; }
    void thingFn() { }
    void containedFn() { if (mDelegate) mDelegate->doDelegateAction(); }
 private:
    Delegate * mDelegate; // Note, we don't own this memory, buyer beware.
};

Теперь вы можете поменять реализацию делегата во время выполнения, тогда как при пересылке вы не можете (и вы можетене хочу, вот почему вы бы это сделали).

Если это ответит на неправильный вопрос, дайте мне знать в комментарии, и я удалю ответ.

2 голосов
/ 19 октября 2011

Это схожие идеи в том, что один объект опирается на помощь другого.Вот как я думаю о двух идеях, учитывая мой сильный уклон Objective-C:

делегирование: Решение должно быть принято, но я не хочу его принимать.Я позволю своему делегату справиться с этим.

Например, в Какао NSTableView использует делегата для настройки поведения таблицы.Делегирование обеспечивает способ настройки одного объекта, позволяя другому объекту, делегату, обеспечивать настройку.Продолжая этот пример, делегат табличного представления реализует интерфейс NSTableViewDelegate , который таблица использует для общения со своим делегатом.

forwarding: Кто-то только что отправил мне сообщение, котороеЯ не понимаю, но я знаю другой объект, который может его реализовать.Я передам вызов этого сообщения этому объекту.

В Какао, опять же, любой класс может реализовать метод -forwardInvocation: .Если сообщение отправляется объекту, который его не реализует, вызывается метод -forwardInvocation: этого объекта, и объект может принять решение передать вызов другому объекту.Этот объект может быть его делегатом, или это может быть какой-то общесистемный обработчик ошибок или что-то еще. NSProxy использует это для реализации всех методов - он просто передает вызов своему главному объекту.

Обратите внимание, что при пересылке не существует определенного делегатаинтерфейс;сообщение просто передается другому объекту.В другом месте вы видите, что я бы назвал переадресацией, когда один объект содержит другой объект, который он использует для реализации некоторого интерфейса.Любые сообщения этому интерфейсу просто перенаправляются на содержащийся объект, который выполняет всю работу.

...