是否可以有一个模板化的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
...
当前,所有消费者都在使用简单的实现。我需要能够在简单和复杂的实现之间动态切换,而无需修改使用者和现有的简单实现。交换实现的机制并不重要。我可以修改所有精美的实现,以采用一个简单的实现对象,然后在使用其自己的精美实现或在每个接口方法调用中委派给该简单实现之间进行动态切换(即,将切换逻辑合并到实现中)。
// 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(...);
}
}
...
}
理想情况下,我不希望使用不相关的切换逻辑来污染实现,因此,我可以执行第三个实现切换的实现:
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_;
...
}
所以,最后,我的问题是...是否可以有一个通用的切换器类,以便将切换逻辑编写一次并可以在需要它的每个接口中重用?像这样的东西:
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),
...);
这是一个简单的(无需考虑其他因素)Switcher类模板,可能是您想要的:
template<typename first, typename second, typename base>
class Switcher{
public:
Switcher(first& _first, second& _second):first_object(&_first), second_object(&_second), active(first_object){}
void switch_them(){
if(active == first_object) active = second_object;
else active = first_object;
}
base* operator &()const{
return active;
}
base* operator ->()const{
return active;
}
private:
first* const first_object;
second* const second_object;
base* active;
};
[请注意,正如其他人所建议的,尽管此处使用地址运算符operator&
完全可以,但也可以使用operator ->
以实现类似的功能。我建议仅选择其中之一,以便保留其他以供将来正常使用。
如果是简单的Foo及其简单的派生:
class Foo{
public:
virtual int DoFoo() = 0;
virtual ~Foo(){}
};
class SimpleFoo:public Foo{
public:
int DoFoo(){
return 0;
}
};
class FancyFoo:public Foo{
public:
int DoFoo(){
return 1;
}
};
简单用法如下:
int main() {
Foo* foo_pointer;
SimpleFoo simplefoo;
FancyFoo fancyfoo;
Switcher<SimpleFoo, FancyFoo, Foo> switcher(simplefoo, fancyfoo);
foo_pointer = &switcher;
std::cout << foo_pointer->DoFoo() << std::endl;
std::cout << switcher->DoFoo() << std::endl;
switcher.switch_them();
foo_pointer = &switcher;
std::cout << foo_pointer->DoFoo() << std::endl;
std::cout << switcher->DoFoo() << std::endl;
switcher.switch_them();
foo_pointer = &switcher;
std::cout << foo_pointer->DoFoo() << std::endl;
std::cout << switcher->DoFoo() << std::endl;
return 0;
}
最后是简单的结果:
0
0
1
1
0
0
当然,您可以为其添加其他功能。