У меня есть класс, который оборачивает другой класс общего базового типа. Поскольку интерфейс базового типа довольно большой, это требует написания множества сквозных функций. Я ищу способ избежать этого.
Давайте сделаем пример:
Car
/ \
Volvo VolvoWithTrailer
Теперь мне нужно реализовать каждую функцию в автомобильном интерфейсе для VolvoWithTrailer и вызвать соответствующую функцию для обернутого объекта Volvo, за исключением, возможно, GetMaxSpeed (), который возвратит что-то меньшее. В основном у меня будет много функций, таких как
int VolvoWithTrailer::GetNumSeats() {
return mVolvo.GetNumSeats()
}
Очевидный способ решить эту проблему - сделать VolvoWithTrailer подклассом Volvo.
Car
|
Volvo
|
VolvoWithTrailer
но это, кажется, нарушает принцип предпочтения композиции по наследству.
Как еще можно избежать написания всех этих оболочек (язык C ++)? Или - если это ваша позиция - почему я должен просто написать их / просто использовать наследование? Есть ли какое-нибудь волшебство шаблона, которое могло бы помочь с этим?
источник
Ответы:
Я считаю, что вы должны написать все, что вам нужно, чтобы улучшить долговременную стабильность и ремонтопригодность программы. Какой смысл избегать написания 20 строк кода сегодня, если каждый раз, когда вы касаетесь чего-то, что использует этот код, или возвращаетесь, чтобы поддержать этот класс, это стоит вам дополнительные 5 минут или больше, потому что вы не потратили время сегодня?
Таким образом, вопрос становится «что вам нужно написать?» Я не думаю, что вы предоставляете достаточно информации, чтобы иметь возможность дать окончательный ответ, поэтому я просто перечислю некоторые вещи, о которых я бы подумал при принятии решения:
1. Вам нужен объект Trailer сам по себе, сейчас или в обозримом будущем?
Если это так, у вас есть довольно хороший аргумент для создания оболочки вокруг обоих составных объектов, поскольку вам уже придется оборачивать один или другой. Может также быть последовательным.
2. Находится ли какой-либо из трех типов (Car, Trailer, CarWithTrailer) в той области кода, в которую разработчики часто заходят или, по-видимому, становятся таковой?
Если это так, будьте очень осторожны, потому что последствия выбора неправильной вещи могут очень дорого амортизироваться при каждом прикосновении к коду. Если нет, это может не иметь никакого значения, что вы решите. Просто выберите направление и следуйте по нему.
3. Что легче всего понять?
Подходит ли вам какой-то подход, что кто-то, идущий за вами, сразу «получит» то, что вы пытаетесь сделать? Есть ли у ваших товарищей по команде особые предубеждения, которые могут затруднить поддержание одного подхода? Если все вещи равны, выберите решение, которое налагает наименьшую когнитивную нагрузку.
4. Есть ли какие-либо дополнительные преимущества использования одного подхода перед другим?
Одна вещь, которая бросается в глаза, это то, что идея обертки имеет явное преимущество, если вы напишите, что ваш CarWithTrailerWrapper может обернуть любой автомобиль и любой трейлер в CarWithTrailer. Затем вы заканчиваете писать все свои сквозные методы, но вы пишете их только один раз , а не один раз для каждого автомобильного класса.
Это делает ваши первоначальные инвестиции в написание пассивных методов намного дешевле, так как вы добавляете больше автомобилей и трейлеров. Это также помогает уменьшить искушение связать вещи слишком напрямую с Volvo или VolvoWithTrailer, одновременно уменьшая последствия соединения с CarWithTrailerWrapper, поскольку вы можете сделать намного больше с помощью только одной реализации.
Может быть, есть определенные преимущества, которые вы получите бесплатно, используя метод расширения, но я их не вижу.
Итак, похоже, что я сам обговорил идти вперед и заполнить сквозные методы для нетривиальных приложений.
Я не программист на C ++, поэтому я понятия не имею, какие инструменты генерации кода вам доступны. Используемая мной среда IDE может генерировать методы из интерфейса, и я могу добавить шаблоны кода , которые сделают написание проходов довольно безболезненным. Если у вас нет доступа к IDE, которая делает это, вы можете довольно далеко позволить Excel написать код для вас .
источник
И есть твоя проблема.
Интерфейсы должны обрабатывать только одну ответственность. Сохранение их тонкими и сфокусированными ограничивает объем работы, которую вам может понадобиться в случае декоратора, прокси или другой оболочки (в дополнение к упрощению использования, тестирования, поддержки и расширения класса).
источник