Обертывание библиотеки с использованием интерфейсов без необходимости приведения типовC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Обертывание библиотеки с использованием интерфейсов без необходимости приведения типов

Сообщение Anonymous »

Предположим, мой проект использует библиотеку LibFoo, которая обеспечивает свою функциональность через ряд классов, скажем, FooA и FooB. Сейчас существует ряд подобных библиотек (например, LibBar, предоставляющая BarA и BarB), которые предоставляют ту же функциональность, что и LibFoo, и я хочу, чтобы пользователи моего проекта иметь возможность выбирать, какую библиотеку использовать, желательно во время выполнения.

Чтобы это работало, я создал «уровень-оболочку», который определяет интерфейсы, которые я ожидаю от библиотеки. В моем примере этот уровень содержит два интерфейса: IfaceA и IfaceB. Затем для каждой библиотеки, которую я хочу поддерживать, я создаю «уровень реализации», реализующий интерфейсы с использованием одной из библиотек.

Моя проблема теперь заключается в том, как реализовать уровень реализации хорошо. Чтобы продемонстрировать мою проблему, предположим, что у нас есть следующие интерфейсы (показаны на C++, но должны быть применимы к аналогичным языкам):

Код: Выделить всё

class IfaceA
{
public:
virtual void doSomethingWith(IfaceB& b) = 0;
...
};

class IfaceB
{
...
};
Классы на уровне реализации LibFoo будут содержать объекты из соответствующих классов LibFoo. Операции в интерфейсах должны быть реализованы с использованием этих объектов. Отсюда (извините за ужасные названия):

Код: Выделить всё

class ConcreteAForFoo : public IfaceA
{
public:
void doSomethingWith(IfaceB& b) override
{
// This should be implemented using FooA::doSomethingWith(FooB&)
}

private:
FooA a;
};

class ConcreteBForFoo : public IfaceB
{
public:
FooB& getFooB() const
{
return b;
}

private:
FooB b;
};
Проблема заключается в реализации ConcreteAForFoo::doSomethingWith: его параметр имеет тип IfaceB&, но мне нужен доступ к деталям реализации ConcreteBForFoo code>, чтобы иметь возможность правильно реализовать метод. Единственный способ, который я нашел, — это повсеместно использовать уродливые приведения:

Код: Выделить всё

void doSomethingWith(IfaceB& b) override
{
assert(dynamic_cast(&b) != nullptr);
a.doSomethingWith(static_cast(b).getFooB());
}
Поскольку необходимость понижения обычно считается запахом кода, я не могу не думать, что должен быть лучший способ сделать это. Или я изначально неправильно это проектирую?

TL;DR

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

Подробнее здесь: https://stackoverflow.com/questions/272 ... -downcasts
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»