Откуда мы знаем, что предпочтение композиции перед обобщением - это всегда правильный выбор?


9

Независимо от того, существует объект физически или нет, мы можем выбрать его моделирование различными способами. Мы могли бы произвольно использовать обобщение или композицию во многих случаях. Тем не менее, принцип GoF «отдавай предпочтение композиции обобщению [sic]» побуждает нас использовать композицию. Итак, когда мы моделируем, например, линию, мы создаем класс, который содержит два члена PointA и PointB типа Point (композиция) вместо расширения Point (обобщение). Это просто упрощенный пример того, как мы можем произвольно выбирать композицию или наследование для моделирования, несмотря на то, что объекты обычно намного сложнее.

Откуда мы знаем, что это правильный выбор? Это имеет значение, по крайней мере, потому что может быть тонна рефакторинга, чтобы сделать, если это неправильно?


9
Ваш пример на самом деле не работает, потому что вы не можете сказать, что линия - это точка, и поэтому она не соответствует принципу подстановки Лискова, а наследование не подходит.
Дин Хардинг

@Dean: Как вы, наверное, знаете, пример не является центральным. Для записи, линия может быть представлена ​​в виде уравнения, определенного через две точки.
CarneyCode


1
@ Сонго: Похоже, вы полностью упустили суть.
CarneyCode

Разве не обобщение расширяет специализацию?
Тулаинс Кордова

Ответы:


17

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

Откуда нам это знать? Из опыта и опыта других.

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

Но моих анекдотических доказательств должно быть недостаточно. Просто посмотрите в интернете, и у многих людей такой же опыт.


Мне это нравится; воздержаться.
CarneyCode

+1 за «Я никогда не видел ситуации, когда структура композиции нуждалась в рефакторинге в наследство».
Казарк

7

Если вы хотите более сильное эмпирическое правило, кроме «отдавайте предпочтение композиции, а не наследованию», я мог бы предложить что-то вроде этого:

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

Однако, как и все эмпирические правила, как только вы поймете это правило, вы сможете нарушить это правило :)


0

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

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


Это более естественно? Линия не более двух точек, чем это удлиненная точка?
CarneyCode

2
Я никогда не видел определение линии, которое не включает в себя тот факт, что она состоит из 2+ точек. Даже если использовать линейное уравнение, если в вашей области чисел только 1 значение, то это точка, а не линия.
Рог

0

Благосклонность случается, когда оба кандидата готовятся. Задача, указанная в вопросе, не может быть использована для этой учетной записи, поскольку она имеет только параметр композиции.

«Композиция также может использовать обобщение». Имеет ли это утверждение смысл для нас? Если нет, то мы еще не готовы понять правило «благосклонности».

Почему мы предпочитаем Composition, так это то, что Composition предлагает больше возможностей расширения / гибкости, чем обобщение. Это расширение / гибкость относится, главным образом, к динамической гибкости во время выполнения (которая достигается с помощью комбинации интерфейсов и композиции).

Благо не сразу видно. Чтобы увидеть выгоду, вам нужно дождаться следующего неожиданного запроса на изменение. Таким образом, в большинстве случаев те, кто придерживается обобщения, терпят неудачу по сравнению с теми, кто принял композицию (за исключением одного очевидного случая, упомянутого позже). Отсюда и правило. С точки зрения обучения, если вы можете успешно внедрить внедрение зависимостей, вы должны знать, какой из них предпочтительнее и когда. Правило помогает вам принять решение, когда вы не уверены, какой из них выбрать. Опять же, вы должны быть в состоянии увидеть оба варианта в первую очередь в пользу одного.

Описание: Состав: связь уменьшается благодаря наличию нескольких более мелких вещей, которые вы подключаете к чему-то большему, а более крупный объект просто вызывает меньший объект обратно. Обобщение: с точки зрения стороннего API, определение того, что метод может быть переопределен, является более строгим обязательством, чем определение того, что метод может быть вызван (уверен, победа для Обобщения) И никогда не забывайте, что с композицией вы также используете обобщение из интерфейса вместо большого класса. Но, к сожалению, вся заслуга в композиции.


-4

Сегодня я написал около 300 лок. И я не могу вспомнить ни одного принципа, который бы я мог нарушать и не нарушал. Надеюсь, рефакторинг спасет мою душу.

Если абстракция продиктована сторонним API - обычно правильно использовать наследование. В отечественном дизайне сущность должна быть либо абстрактной, либо опечатанной. Абстрактная сущность потенциально должна иметь около 3 наследников. Мне не нравятся точки расширения с одним виртуальным методом. Все выше о моем вкусе. Я не говорю об абстракции интерфейса, это совершенно другая история.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.