【问题标题】:Dynamic switching of implementation in hardware abstraction layer (HAL)硬件抽象层(HAL)中实现的动态切换
【发布时间】:2020-09-21 01:22:18
【问题描述】:

我正在尝试实现一个硬件抽象层 (HAL),以使用所有相同的接口访问几个类似的设备。 问题是,我应该如何实现一个设备类与另一个设备类的实现的动态切换。
以下代码显示了我实际上是如何做到的。 但是,我不确定这个实现是否足够安全。特别是我不确定使用“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();
}

我为所有设备定义了一个具有通用功能的基类(在本例中,这只是Identify() 方法)。 然后我为设备实现派生类Derived1Derived2。 我想在主代码中的这些实现之间切换(例如,设备选择器或类似的东西。在示例中,这只是通过从主代码调用 setter 来完成)。
为了实现切换,我添加了一个类ImplementationDispatcher,它为当前实现添加了一个shared_ptr,用于隔离目的,类似于pimpl-idiom。 切换是通过向切换器类提供基类的子类的新实例来完成的。

【问题讨论】:

    标签: c++ factory derived-class hal pimpl


    【解决方案1】:

    看起来像是过度设计。只需实现您的抽象设备并将适当的实例传递给Work。至少在您的示例中,根本不需要ImplementationDispatcher

    【讨论】:

    • 感谢您的回答。我看到你指出。但是,Work 方法不应该“知道”它调用哪个实现。实际的实现意味着在不同位置的一些 UI 处理程序或初始化代码中设置。我可以在Actor 类中直接持有shared_ptr&lt;Base&gt; Impl,但是Actor 取决于实现方式的切换方式。
    • 这完全可行:只要有Work(Base&amp;),你就可以实现class Device1: public Baseclass Device2: public Base 等。我的建议类似于访问者模式,当你解耦你的工作时来自实际工人。
    • 好的,再次感谢您。我来看看访客模式。也许我只是想实现正确的设计模式,尽管访问者可能更适合。
    • 我认为访客提示很有帮助。
    猜你喜欢
    • 2017-03-29
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 2012-12-01
    • 1970-01-01
    相关资源
    最近更新 更多