I am faced with the following conundrum: Our software has an abstract base class for algorithm objects. All these objects have a common execute()
method, e.g.:
class Algorithm
{
public:
// [...]
virtual void execute() = 0;
// [...]
};
For each algorithm that we want to implement, we simply inherit from the base class and store all loaded algorithm objects in a central location. So far, so good.
The problem now lies in the parameters of an algorithm. We want to be able to describe for each algorithm the parameters that need to be set (by an external class). To this end, we gave each algorithm a ParameterList
object that contains its parameters. I should clarify that for us, a parameter consists of some kind of type (such as int
) and a label (such as "Number of iterations).
The problem now begins when we want to connect the ParameterList
to some kind of GUI. Obviously, our algorithms should have no "knowledge" of the graphical API (Qt, GTK, etc.) that we are using. Yet, on the same side, we want to be able to describe algorithm paramters semantically, for example by specifying that the algorithm requires a filename. How this filename is then displayed is up to the GUI.
Is there a way to combine this ParameterList
with some kind of semantic type knowledge?
I realize that this question sounds very vague. However, I am not permitted to post any non-trivial code examples (for NDA reasons). So, has anyone been faced with a similar problem in the past?
To wrap it up: We want our objects to describe the parameters they require to a GUI, without knowing the exact details of the GUI.
One option here might be to use the visitor pattern. You can create a base class like this:
class Parameter {
public:
virtual ~Parameter() {} // Polymorphic classes need virtual dtors.
virtual void accept(ParameterVisitor& v) = 0;
};
You could define subclasses like these:
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);
}
};
Note that in each accept
member function, the type of *this
is the static type of the class - namely, IntParameter&
in the first case, and FilenameParameter&
in the second case.
You can then define a base class ParameterVisitor
class like this:
class ParameterVisitor {
public:
virtual ~ParameterVisitor() {} // Polymorphic classes need virtual dtors.
virtual void visit(IntParameter& p) {}
virtual void visit(FilenameParameter& p) {}
/* .. etc. .. */
};
You can then subclass this visitor to get back the type information:
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. */
}
};
Your ParameterList
class can then just store a list of Parameter*
s. You can then build the GUI by instantiating the appropriate visitor type and then having its visit
callbacks do all the widget construction. This ends up being type-safe and recovers the information you need. It does have the drawback that every time you create a new parameter type, you have to add a new member function visit
to the ParameterVisitor
class, but you'd need to do that anyway to do all the GUI building.
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With