硬件抽象层(HAL)实现的动态切换
Dynamic switching of implementation in hardware abstraction layer (HAL)
我正在尝试实现一个硬件抽象层 (HAL) 以使用所有相同的接口访问多个相似的设备。
问题是,我应该如何实现一个设备 class 与另一个设备的实现的动态切换。
下面的代码显示了我实际上是如何做到的。
但是,我不确定这个实现是否足够安全。特别是我不确定使用 'shared_ptr' 来切换实现是否是正确的方法,或者使用工厂模式或更多抽象是否更好。
您会推荐什么来实现这样的动态 HAL?
#include <iostream>
#include <string>
#include <memory>
using namespace std;
// Common HAL base class
struct Base {
virtual string Identify() {return string("Baseclass");}
Base() {cout << "Base Constructor" << '\n';}
virtual ~Base() {cout << "Base Destructor" << '\n';}
// Important to make destructor virtual so that destructor of derived classes is invoked, too
};
// HAL Device 1 Implementation
struct Derived1: public Base {
string Identify() override {return string("Derived 1 class");}
Derived1() {cout << "Derived1 Constructor" << '\n';}
~Derived1() {cout << "Derived1 Destructor" << '\n';}
};
// HAL Device 2 Implementation
struct Derived2: public Base {
string Identify() override {return string("Derived 2 class");}
Derived2() {cout << "Derived2 Constructor" << '\n';}
~Derived2() {cout << "Derived2 Destructor" << '\n';}
};
// Switches implementation via setting a pointer to a class instance
struct ImplementationDispatcher {
shared_ptr<Base> Impl = make_shared<Base>();
Base& Implementation() {return *Impl;}
void SetImplementation(shared_ptr<Base> impl) {Impl = impl;}
};
// Top level class which calls HAL device functions
struct Actor {
ImplementationDispatcher HAL;
void Work() {cout << HAL.Implementation().Identify() << '\n';}
void SetActor(shared_ptr<Base> newImpl) {HAL.SetImplementation(newImpl);}
};
int main()
{
Actor actor;
actor.Work();
actor.SetActor(make_shared<Derived1>());
actor.Work();
actor.SetActor(make_shared<Derived2>());
actor.Work();
}
我定义了一个基础 class,它具有所有设备的通用功能(在这个例子中,这只是 Identify()
方法)。
然后我为设备实现 Derived1
和 Derived2
导出 classes。
我想在主代码中的这些实现之间切换(例如设备选择器或类似的东西。在示例中,这只是通过从主代码调用 setter 来完成)。
为了实现切换,我添加了一个 class ImplementationDispatcher
,其中包含一个 shared_ptr
到当前实现以进行隔离,类似于 pimpl-idiom。
切换是通过向切换器 class 提供来自 base.
的新子 class 实例来完成的。
似乎设计过度了。只需实现您的抽象设备并将适当的实例传递给 Work
。至少在您的示例中,根本不需要 ImplementationDispatcher
.
我正在尝试实现一个硬件抽象层 (HAL) 以使用所有相同的接口访问多个相似的设备。
问题是,我应该如何实现一个设备 class 与另一个设备的实现的动态切换。
下面的代码显示了我实际上是如何做到的。
但是,我不确定这个实现是否足够安全。特别是我不确定使用 'shared_ptr' 来切换实现是否是正确的方法,或者使用工厂模式或更多抽象是否更好。
您会推荐什么来实现这样的动态 HAL?
#include <iostream>
#include <string>
#include <memory>
using namespace std;
// Common HAL base class
struct Base {
virtual string Identify() {return string("Baseclass");}
Base() {cout << "Base Constructor" << '\n';}
virtual ~Base() {cout << "Base Destructor" << '\n';}
// Important to make destructor virtual so that destructor of derived classes is invoked, too
};
// HAL Device 1 Implementation
struct Derived1: public Base {
string Identify() override {return string("Derived 1 class");}
Derived1() {cout << "Derived1 Constructor" << '\n';}
~Derived1() {cout << "Derived1 Destructor" << '\n';}
};
// HAL Device 2 Implementation
struct Derived2: public Base {
string Identify() override {return string("Derived 2 class");}
Derived2() {cout << "Derived2 Constructor" << '\n';}
~Derived2() {cout << "Derived2 Destructor" << '\n';}
};
// Switches implementation via setting a pointer to a class instance
struct ImplementationDispatcher {
shared_ptr<Base> Impl = make_shared<Base>();
Base& Implementation() {return *Impl;}
void SetImplementation(shared_ptr<Base> impl) {Impl = impl;}
};
// Top level class which calls HAL device functions
struct Actor {
ImplementationDispatcher HAL;
void Work() {cout << HAL.Implementation().Identify() << '\n';}
void SetActor(shared_ptr<Base> newImpl) {HAL.SetImplementation(newImpl);}
};
int main()
{
Actor actor;
actor.Work();
actor.SetActor(make_shared<Derived1>());
actor.Work();
actor.SetActor(make_shared<Derived2>());
actor.Work();
}
我定义了一个基础 class,它具有所有设备的通用功能(在这个例子中,这只是 Identify()
方法)。
然后我为设备实现 Derived1
和 Derived2
导出 classes。
我想在主代码中的这些实现之间切换(例如设备选择器或类似的东西。在示例中,这只是通过从主代码调用 setter 来完成)。
为了实现切换,我添加了一个 class ImplementationDispatcher
,其中包含一个 shared_ptr
到当前实现以进行隔离,类似于 pimpl-idiom。
切换是通过向切换器 class 提供来自 base.
似乎设计过度了。只需实现您的抽象设备并将适当的实例传递给 Work
。至少在您的示例中,根本不需要 ImplementationDispatcher
.