Возможно ли иметь шаблонный класс c ++, который в общем случае реализует интерфейс T и динамически делегирует вызовы одному или нескольким обернутым объектам, которые реализуют T?
Как обычно, лучше всего использовать код, чтобы объяснить, что я пытаюсь сделать:
// There are many interfaces:
class Foo {
public:
virtual ... DoFoo(...);
...
}
class Bar {
public:
virtual ... DoBar(...);
...
}
class InterfaceN { ... }
...
// Each interface has multiple implementations:
class SimpleFoo : public Foo { ... }
class FancyFoo : public Foo { ... }
class SimpleBar : public Bar { ... }
class FancyBar : public Bar { ... }
class SimpleInterfaceN : public InterfaceN { ... }
class FancyInterfaceN : public InterfaceN { ... }
...
// There are many consumers of these interfaces:
class ConsumerA {
public:
ConsumerA(Foo foo, Bar bar, ...);
...
}
class ConsumerB { ... } // uses Foo, Interface2, Interface5
class ConsumerC { ... } // uses Bar, Interface2
...
В настоящее время все потребители используют простые реализации. Мне нужно иметь возможность динамически переключаться между простыми и причудливыми реализациями без изменения потребителей и существующих простых реализаций. Неважно, что это за механизм, который меняет реализации. Я мог бы изменить все причудливые реализации так, чтобы они воспринимали простой объект реализации, а затем динамически переключаться между использованием собственной причудливой реализации или делегировать простой реализации в каждом вызове метода интерфейса (т. Е. Включать переключение логики c в реализации).
// For each interface, add switching logic to fancy implementation:
class FancyFoo : public Foo {
public:
FancyFoo(SimpleFoo* simple_foo, ...) override;
... DoFoo(...) override {
if (use_fancy) {
// fancy implementation
...
} else {
return simple_foo_->DoFoo(...);
}
}
...
}
В идеале я предпочитаю не загрязнять реализации несвязанными логиками переключения c, поэтому вместо этого я могу сделать третью реализацию, которая выполняет переключение:
class FooSwitcher : public Foo {
public:
FooSwitcher(Foo* first_foo, Foo* second_foo) {
active_foo_ = first_foo;
inactive_foo_ = second_foo;
}
... DoFoo(...) {
return active_foo_->DoFoo(...);
}
void SwitchFoos() {
swap(active_foo_, inactive_foo_);
}
...
private:
Foo* active_foo_;
Foo* inactive_foo_;
...
}
Итак, наконец, мой вопрос это ... Возможно ли иметь обобщенный класс c switcher, чтобы лог переключения c записывался один раз и мог быть повторно использован для каждого интерфейса, который в этом нуждается? Примерно так:
template <typename T>
class Switcher : public T {
public:
Switcher(T first_impl, T second_impl) { ... }
***magic that forwards/delegates all calls to any T methods to active_impl_***
private:
T active_impl_;
T inactive_impl_;
}
... и будет использоваться что-то вроде этого:
ConsumerA consumer_a = new ConsumerA(
Switcher<Foo>(simple_foo, fancy_foo),
Switcher<Bar>(simple_bar, fancy_bar),
...);