Композиция против Делегации - PullRequest
18 голосов
/ 26 января 2010

Есть ли разница с точки зрения реализации, как то, как дизайн композиции может отличаться от делегирования. Например, приведенный ниже код, по-видимому, выполняет делегирование, поскольку пользователь не может получить доступ к составленному объекту (то есть «a») без использования b. Следовательно, пользователь должен будет вызывать интерфейсы класса b, а затем «класс b» вызывать соответствующие интерфейсы «класса a», делая его делегирование. Имеет ли это смысл?

Class A {
friend class B;
private: 
A(){}; //dont want user to instantiate this class object since it wont sense without any context. Just like a room with no house.
void PrintStructure(){};
};

Class B{
public:
void PrintStructure(){a.PrintStructure();} //delegate

private:
A a; //composition
};

Ответы [ 3 ]

36 голосов
/ 26 января 2010

Термин «композиция» обычно используется в терминах объектного моделирования как выражение отношения «имеет» и является формой ассоциации (другой является агрегацией). Обычно это противопоставляется «наследованию» (отношения «is-a»). Итак:

В чем разница между составом и агрегацией? Композиция подразумевает, что ребенок не может существовать без контекста родителя.

Например, в доме есть одна или несколько комнат. Это композиционные отношения. Удалите дом и комнаты тоже перестанут существовать. Дом также имеет ряд жителей, являющихся примерами человека. Это агрегирующие отношения, потому что эти люди существуют вне контекста этого дома.

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

Вы заметите, что и A и B из вашего примера имеют один и тот же внешний интерфейс. Чаще всего делают что-то вроде этого:

// this represents an interface
class A {
public:
  virtual void printStructure() = 0;
}

с конкретными классами:

class ConcreteA : A {
public:
  virtual void printStructure() { ... }
}

и

class DelegateA : A {
public:
  DelegateA(A& a) { this.a = a; }
  virtual void printStructure() { a.printStructure(); }
private:
  A a;
}

Извините, возможно, мои синтаксические ошибки C ++. Я немного ржавый.

8 голосов
/ 26 января 2010

Я вижу пару отличий:

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

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

4 голосов
/ 26 января 2010

Композиция о взаимоотношениях между объектами.

Делегация касается передачи работы от одного объекта к другому.

Это на самом деле разные (но иногда связанные) проблемы.

То, что у вас есть, это B, состоящий из A (B относится к A). B также делегирует свой единственный метод A.

Но поскольку B использует A индивидуально (полностью инкапсулировано в черном ящике B), я бы не назвал использование B композицией. Я бы использовал «композицию» только в том случае, если к классу A можно получить доступ из B. Здесь важно то, что логическая модель B «has-a» A.

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

Тем не менее, эти вещи действительно важны только для инструментов моделирования PHB и UML. Или, может быть, если вы изучаете шаблоны проектирования. Я бы не стал слишком зацикливаться на этом.

[PHB => Волосатый босс]

...