11

我面临以下难题:我们的软件有一个算法对象的抽象基类。所有这些对象都有一个共同的execute()方法,例如:

class Algorithm
{
public:
  // [...]
  virtual void execute() = 0;
  // [...]
};

对于我们想要实现的每个算法,我们只需从基类继承并将所有加载的算法对象存储在一个中心位置。到目前为止,一切都很好。

现在的问题在于算法的参数。我们希望能够为每个算法描述需要设置的参数(通过外部类)。为此,我们给每个算法一个ParameterList包含其参数的对象。我应该澄清一下,对我们来说,参数由某种类型(例如int)和标签(例如“迭代次数”)组成。

当我们想要连接ParameterList到某种 GUI 时,问题就开始了。显然,我们的算法不应该“了解”我们正在使用的图形 API(Qt、GTK 等)。然而,在同一方面,我们希望能够从语义上描述算法参数,例如通过指定算法需要一个文件名。然后如何显示此文件名取决于 GUI。

有没有办法将它ParameterList与某种语义类型的知识结合起来?

我意识到这个问题听起来很模糊。但是,我不允许发布任何重要的代码示例(出于 NDA 原因)。那么,过去有没有人遇到过类似的问题?

总结一下:我们希望我们的对象在不知道 GUI 的确切细节的情况下向 GUI 描述它们所需的参数。

4

1 回答 1

9

这里的一种选择可能是使用访问者模式。您可以像这样创建一个基类:

class Parameter {
public:
    virtual ~Parameter() {} // Polymorphic classes need virtual dtors.

    virtual void accept(ParameterVisitor& v) = 0;
};

您可以定义如下子类:

class IntParameter: public Parameter {
public:
     virtual void accept(ParameterVisitor& v) {
          v.visit(*this);
     }
};
class FilenameParameter: public Parameter {
public:
     virtual void accept(ParameterVisitor& v) {
          v.visit(*this);
     }
};

请注意,在每个accept成员函数中,类型*this是类的静态类型——即,IntParameter&在第一种情况下,FilenameParameter&在第二种情况下。

然后,您可以ParameterVisitor像这样定义一个基类类:

class ParameterVisitor {
public:
    virtual ~ParameterVisitor() {} // Polymorphic classes need virtual dtors.

    virtual void visit(IntParameter& p) {}
    virtual void visit(FilenameParameter& p) {}
    /* .. etc. .. */
};

然后,您可以对该访问者进行子类化以获取类型信息:

class Gui1ParameterVisitor: public ParameterVisitor {
public:
    virtual void visit(IntParameter& p) {
        /* ... use GUI1 to create a field for an integer. */
    }
    virtual void visit(FilenameParameter& p) {
        /* ... use GUI1 to create a field for a filename. */
    }
};

class Gui2ParameterVisitor: public ParameterVisitor {
public:
    virtual void visit(IntParameter& p) {
        /* ... use GUI2 to create a field for an integer. */
    }
    virtual void visit(FilenameParameter& p) {
        /* ... use GUI2 to create a field for a filename. */
    }
};

然后,您的ParameterList班级可以只存储Parameter*s 的列表。然后,您可以通过实例化适当的访问者类型来构建 GUI,然后让其visit回调完成所有小部件的构建。这最终是类型安全的并恢复了您需要的信息。它确实有一个缺点,即每次创建新的参数类型时,都必须向类中添加新的成员函数visitParameterVisitor但无论如何您都需要这样做才能完成所有 GUI 构建。

希望这可以帮助!

于 2012-05-15T19:32:42.587 回答