Мой заголовок, вероятно, не велик - я открыт для предложений.
Сейчас у меня есть библиотечный код, который обеспечивает базовую функциональность для класса, имеющего некоторые зависимости. Код выглядит примерно так:
class Fan { /* ... */ };
class PanametricFan : public Fan { /* ... */ };
class DeskFan : public Fan { /* ... */ };
class LogCasing { /* ... */ };
class MalleableLogCasing : public LogCasing { /* ... */ };
struct EncabulatorDependencies
{
Fan * fan;
LogCasing * casing;
};
EncabulatorDependencies setupDependencies
(const std::string & confFile) { /* ... */ }
class Encabulator
{
public:
Encabulator(const EncabulatorDependencies & dependencies);
// ...
};
Теперь в коде пользователя у меня есть что-то вроде этого:
class TurboEncabulator : public Encabulator { /* ... */ }
Теперь пока функционал базового класса в Encabulator может отлично работать с любым типом вентилятора и LogCasing , для TurboEncabulator особенно требуется Panametric Fan и MalleableLogCasing на работу.
Конечно, если файл конфигурации был настроен правильно, то setupDependencies
даст мне правильный тип вентилятора и корпуса, который я мог бы просто привести их, например так:
TurboEncabulator::TurboEncabulator(const EncabulatorDependencies & deps)
: Encabulator(deps)
{
myPanametricFan = dynamic_cast<PanametricFan *>(deps.fan);
myMalleableCasing = dynamic_cast<MalleableLogCasing *>(deps.casing);
//..
}
Но я бы хотел сделать что-нибудь более безопасное для типов.
Моя идея состояла в том, чтобы заменить EncabulatorDependencies списком вариантов и получить что-то, что скажет, скажем, "дай мне * 1029"* из этой коллекции "(включая, скажем, указатель на любой производный класс Fan
) или" дайте мне PanametricFan *
из этой коллекции ". Что-то вроде
Encabulator::Encabulator(const EncabulatorDependencies & deps)
{
myFan = deps.get<Fan *>();
myCasing = deps.get<LogCasing *>();
}
в библиотеке и
TurboEncabulator::TurboEncabulator(const EncabulatorDependencies & deps)
{
myPanametricFan = deps.get<PanametricFan *>();
myMalleableCasing = deps.get<MalleableLogCasing *>();
}
в коде пользователя.
Тогда метод setupDependencies
может просто создать соответствующий объект производного типаи бросить указатель в список зависимостей, Encabulator
может иметь Fan *
, TurboEncabulator
может иметь PanametricFan *
, и если файл конфигурации не настроен должным образом, система может выдать нормальное сообщение об ошибке.
Конечно, я могу вспомнить пару «грязных» способов, которыми это может быть достигнуто - EncabulatorDependencies
может просто содержать отдельные Fan *
, Panametric Fan *
, Desk Fan *
и т. Д. Указатели и клиентнапример, код может получить тот, который ему нужен, но я надеялся, что существует «правильный» способ сделать это, не требуя дополнительных затрат на обслуживание.