0

我正在使用 C++ 做一些算法工作。我的算法有一些选项,我需要能够以尽可能少的努力添加到我的程序中。我目前正在使用代码。

一切都按预期工作:我在我的程序中添加了一些代码,这样我就可以使用类似-oopt1=val1,opt2=val2的参数调用二进制文件,并且自动设置选项。

问题是我同时也在编写一个 GUI。现在必须能够使用 GUI 设置/请求每种选项。但是,我可能需要一个用于整数值的旋转框和一个用于布尔选项的复选框。我使用 Qt 作为工具包,所以我可以编写一个返回QWidget*适当基类的成员函数。

但是,我不希望在我声明我的选项的标头中出现任何特定于 GUI 的代码,因为我想将 GUI 与程序的其余部分分开。我可以将任何 Option 子类化以创建适当的QWidget*,但如果我得到 的列表OptBase*,我将不知道我应该创建什么样的小部件。

有什么方法可以让 GUI 与程序的其余部分分开,同时仍然能够创建适当的小部件?

4

2 回答 2

2

对我来说,解决方案是创建一个抽象工厂:工厂应该有一个接口,其中包含两个抽象方法 createBoolOption 和 CreateChoiceOption。可能需要更多方法然后您可以对该接口进行两个具体实现,其中一个返回与您现在所做的相同的实现,但是当您在 QT 中运行时,您可以使用不同的实现返回一个确实知道的 optbase 派生类如何创建小部件。您甚至可以使用多重继承(即第二个接口),这样您就不必在第一个接口中创建一个方法来专门创建一个小部件。当然,在运行 QT 应用程序时,当您想要创建小部件时,您必须显式地转换到第二个界面。抽象工厂本身应该传递给 algobase 的构造函数。

class ifactory{
public:
  virtual Option<bool>* createBoolOption()=0;
  virtual ChoiceOption<Mode>*  createChoiceOption()=0;
  virtual Widget* createWidget()=0; //here or in another interface
};

class ConcreteNonGuiFactory : public ifactory{
  virtual Option<bool>* createBoolOption();
  virtual ChoiceOption<Mode>* createChoiceOption();
  virtual Widget* createWidget()={;}; 
};

class ConcreteGuiFactory : public ifactory{
  virtual Option<bool>* createBoolOption();
  virtual ChoiceOption<Mode>* createChoiceOption();
  virtual Widget* createWidget(); 
}; 

class Algo1 : public AlgoBase{
public:
   Algo1(ifactory& f):factory(f){
      ChoiceOption<Mode>* opt = factory.createChoiceOption();
   }
private:
   ifactory factory;
}

如果小部件的创建是在不同的界面中,您可以减少您的依赖关系。在此示例中,至少必须前向声明小部件。

于 2013-06-25T15:29:24.570 回答
1

您需要一组变量供 setter(GUI、命令行解析器)和 getter(算法函数)访问。QVariant 应该没问题。由于您的选项有名称,它们也有隐式类型。Getter 应按名称检索值并显式进行类型转换。Setter 不应该关心 - QVariant 会。

创建一个具有选项名称映射的单例实例。实现由 GUI 值更改信号触发的插槽,在地图中设置值。例如:

class VarTable
{
   static VarTable & instance(){ static VarTable inst; return inst; }
   QMap<QString, QVariant> _map;
public: 
   void setVar( QString n, QVariant v ){ _map[n] = v };
   QVariant getVar( QString n ) const { return _map[n]; }
};

//Call in Slot triggered by a value-change signal (e.g. QEditLine::returnPressed)
VarTable::instance().setVal( "option1", val1 );

//Regrieve in non-gui code
QString option1 = VarTable::instance().getVal( "option1" ).toString();

问候

PS:我没有编译代码,我有一些错别字。

于 2013-06-25T15:28:46.280 回答