在库中定义了一个类:
class fromLib{};
用作调用库中实现的方法的参数:
method_from_lib(const fromLib& from_lib){};
我想把这个方法包装在一个接口中
class Methods{
virtual invoke_method(const& genericArg)
}
其中类别CCD_ 1是CCD_。
一个简单的实现是:
class MethodImpl: public Methods {
invoke_method(const genericArg& arg) {
method_from_lib(arg); // this is not going to work since the argument is not an instance of `fromLib` nor convertible nor does it inherit from it.
};
}
在理想的情况下,我会使类fromLib
直接继承自genericArg
。然而,这是不可能的,因为这门课来自一个我真的不想碰的图书馆。
我该如何实现fromLib
的包装器,它也是genericArg
的实现。
这样做的动机如下:
库提供了一些带有签名method_from_lib(const fromLib& from_lib){};
的方法,我们可能会使用,也可能不会使用。我们可能希望使用该方法或其他实现。如果我们使用其他实现,函数的参数也需要更改,因为参数fromLib
与库提供的实现紧密耦合。
因此,为方法本身提供一个接口是很简单的,然而,这个问题的目的是如何将参数fromLib
推广到某个接口中。这样我们的界面就会像一样
类方法{虚拟invoke_method(const&genericArg)}
当我们想使用库来实现这个案例时,实现相当容易——我们只需从库中调用方法,即
invoke_method(const TYPE& arg) {
method_from_lib(arg);
};
现在,正如您所看到的,实现这个方法要么需要genericArg
0是genericArg
,要么需要从它继承的某个类。这里的问题是,method_from_lib
需要类型fromLib
,我们不能直接将其作为genericArg
的子级,因为该类型包含在第三方库中
我想您正在寻找一个适配器。
https://refactoring.guru/design-patterns/adapter/cpp/example
用法示例:适配器模式在C++代码中非常常见。它是通常在基于一些遗留代码的系统中使用。在这种情况下,适配器使遗留代码能够与现代类一起使用。
标识:适配器可由构造函数识别,该构造函数不同抽象/接口类型的实例。当适配器接收到对其任何方法的调用,它将参数转换为适当的格式,然后将调用定向到一个或多个方法包裹对象的。
您声明不想接触fromLib类。假设fromLib所需的数据肯定是要执行的操作所必需的,那么您必须实现自己的结构,该结构包含所需数据。
然后可以将这个自己的结构传递给适配器。然后,适配器将把它传递给lib,并返回正确的结果。如果要切换出lib,则切换出适配器以使用新的lib。代码的其余部分将保持不变。
例如:
class fromLib{
int degrees;// You can't change this even if you'd want to use radians in your program.
}
struct myActualRequiredData {
double radians;// Choose something here which works well within your own program.
}
class MethodsTarget{
virtual invoke_method(const myActualRequiredData& data);
}
class MethodsAdapter : public MethodsTarget{
virtual invoke_method(const myActualRequiredData& data) {
fromLib myFromLib = {
.degrees = radians * 360 / PI;// Or so. I currently don't care, not what your question is about. In any case, here's where you do all the work to speak the libraries language.
};
method_from_lib(myFromLib);
}
};
MethodsAdapter adapter;
adapter.invoke_method({
.radians = 0.2
});
// Oh look I found a better lib
class fromLib2{
std::string degrees;
}
class MethodsAdapter2 : public MethodsTarget {
virtual invoke_method(const myActualRequiredData& data) {
fromLib2 myFromLib = {
.degrees = std::string(radians * 360 / PI);
};
method_from_lib(myFromLib);
}
}
MethodsAdapter2 adapter2;
adapter.invoke_method({
.radians = 0.2
});
此示例表明,在使用适配器模式时,更改库将导致最小的调整。
如有必要,可与指向MethodsTarget的指针一起使用。但通常对于libs来说,仅仅拥有一个适配器类就足够了。无论如何,你不会热交换。
我建议使用组合并将成员传递到库调用中:
struct GenericArg{
fromLib member;
};
void wrapper(const GenericArg& arg){
method_from_lib(arg.member);
}