3

我知道策略和抽象工厂设计模式——但是它们并不能解决我当前的问题:

我正在创建一个提供非常基本 GUI 的 C++ 库。但是我希望用户能够在编译时选择使用哪个 GUI 库(比如 Qt 或 FLTK)来实际呈现 GUI。然而,用户应该只需要了解我的库中的方法。

应该可以使用 Qt 后端或 FLTK 后端编译相同的代码而无需任何更改。

我想到了类似的东西:

class A
{
  // do things that are not specific to QT or FLTK here as there are many 
  // methods I will need independent of the backend
}

class QT_A : public A
{
  // Implement the actual creation of a window, display of a widget here using Qt
}

class FLTK_A : public A
{
  // Implement the actual creation of a window, display of a widget here using FLTK
}

问题是我不希望用户知道QT_Aor FLTK_A。用户(开发人员)应该只处理A. 另外,我不能同时拥有这两种变体,因为我不希望我的库同时依赖于 Qt 和 FLTK;只是在编译时选择的那个。

4

3 回答 3

4

Pimpl 成语可能是另一种选择。它允许您创建一个不依赖于框架的成员的通用接口。

class A
{
  struct impl;
  std::unique_ptr<impl> pimpl; // or scoped_ptr/auto_ptr on non-C++11
public:
  A();
  ~A();
 void do_sth();
};

然后,源文件可以根据后端提供不同的 impl 实现。

#ifdef QT
struct A::impl : QWidget { // Make it polymorphic, if you need
  QImage img;
  QString data;
};

void A::do_sth()
{
  impl->make_it(); // full access to the Qt things
}

A::A()
  : pimpl(new ...)
{
}

A::~A() {} // no need for delete thanks the smart pointer

#endif
于 2013-01-23T17:52:07.517 回答
4

一个选项是另一个答案中描述的 Pimpl 成语。

另一种选择是工厂返回指向接口类的指针:

std::unique_ptr<A> make_A()
{
#if defined(USING_QT)
    return std::unique_ptr<A>(new QT_A(...));
#elif defined(USING_FLTK)
    return std::unique_ptr<A>(new FLTK_A(...));
#else
    #error "No GUI library chosen"
#endif
}
于 2013-01-23T17:59:17.437 回答
3

不需要花哨的图案。

你分发

  1. A的标题;
  2. 一个包含AQT_Amake_A函数的库;
  3. 另一个包含 的库AFLTK_A以及另一个make_A函数实现。

用户链接到任一库。

于 2013-01-23T18:12:12.590 回答