用C ++模式替换GUI生成器的运行时类型选择

时间:2018-11-28 02:30:52

标签: c++ polymorphism

我正在为从Node类创建的某些数据创建 GUI生成器。每个Node子类都代表不同类型的数据(例如StringNode,IntNode)。

在运行时,我不知道节点的派生类型。我觉得我唯一的解决方案是拥有大量if语句列表:

if (auto stringNode = dynamic_cast<StringNode*>(node)) {
    /* Generate text input */
} else if (auto intNode = dynamic_cast<IntNode*>(node)) {
    /* Generate spin box */
} 
// etc...

这似乎效率低下,需要仔细排序,因此派生类型位于它们继承的类型之上。

还有另一种使用多态性的方法吗?

  • GUI生成器不在定义Node的库中。 每个节点的GUI可能对于派生类型(例如日期选择器)是唯一的。

  • 我无法在节点上添加虚拟generateGui()方法,因为这将需要在库中生成GUI。

  • 我可以编辑Node类。

  • 可以在该库之外添加
  • Node子类,并且还应允许生成其GUI。

  • 我看过Visitor PatternStrategy Pattern,但我认为它们并不适合,因为并非所有类都可以使用,或者GUI生成器在库中不可用。

1 个答案:

答案 0 :(得分:0)

我可以提供此实现:

enum class NodeType { Unknown, String, Int, Float };
using CreateFunc = void(*)(Node *node);
using TypeFunc = bool(*)(Node *node);

// define type-checkers:
bool IsStringNode(Node *node)
{
    return dynamic_cast<StringNode*>(node) != nullptr;
}
bool IsIntNode(Node *node)
{
    return dynamic_cast<IntNode*>(node) != nullptr;
}
bool IsFloatNode(Node *node)
{
    return dynamic_cast<FloatNode*>(node) != nullptr;
}


class GuiGenerator
{
public:
// define specific creators:
    static void CreateStringGui(Node *node) { cout << "Creating String Gui" << endl; }
    static void CreateIntGui(Node *node)  { cout << "Creating Int Gui" << endl; }
    static void CreateFloatGui(Node *node)  { cout << "Creating Float Gui" << endl; }
    //void Create(<Some other node>) {}
};

map<NodeType, CreateFunc> Creators =
{
    { NodeType::String, &GuiGenerator::CreateStringGui },
    { NodeType::Int, &GuiGenerator::CreateIntGui },
    { NodeType::Float, &GuiGenerator::CreateFloatGui }
};

NodeType GetType(Node *node)
{
    vector<pair<NodeType, TypeFunc>> types =
    {
        { NodeType::String, &IsStringNode },
        { NodeType::Int, &IsIntNode },
        { NodeType::Float, &IsFloatNode }
    };

    for(auto &a : types)
        if(a.second(node))
            return a.first;
    return NodeType::Unknown;
}

// And here is it: your simplified function
//
static void CreateGUI(Node *node)
{
    auto type = GetType(node);
    Creators[type](node);
}

您可以像这样使用它:

Node *node1 = new StringNode();
Node *node2 = new IntNode();
Node *node3 = new FloatNode();

CreateGUI(node1);
CreateGUI(node2);
CreateGUI(node3);

没有提供用于简化的错误处理。