Лучший способ реализовать работающие действия с древовидными узлами, предпочтительно не используя посетителей

У меня есть пользовательский интерфейс со структурным видом слева и средство просмотра справа (немного как почтовый клиент). Средство просмотра на праве отображает деталь того, что я выбрал в дереве слева.

Пользовательский интерфейс имеет, "добавляют", "редактируют" и "удаляют" кнопки. Эти кнопки действуют по-другому в зависимости от того, какой "узел" в дереве выбран.

Если у меня есть узел конкретного типа, выбранного, и пользовательские щелчки "редактирование", то я должен открыть соответствующее диалоговое окно редактирования для того конкретного типа узла с деталями того узла.

Теперь, существует много различных типов узла, и реализация класса посетителя чувствует себя немного грязной (currenty, у моего посетителя есть приблизительно 48 записей....). Это действительно работает приятно, хотя - в основном для редактирования что-то как класс OpenEditDialog, который наследовал посетителя, и открывает соответствующее диалоговое окно редактирования:

abstractTreeNode-> принимают (OpenEditDialog ());

Проблема, я должен реализовать абстрактный класс посетителя для каждого "действия", которое я хочу выполнить на узле, и по некоторым причинам я не могу сдержать взгляды, что я пропускаю прием.

Другой путь мог для реализации функций в самих узлах:

abstractTreeNode->openEditDialog();

Я - ording узел вокруг немного здесь, поэтому возможно, это лучше:

abstractTreeNode->editClickedEvent();

Я не могу не думать, что это загрязняет узел все же.

Я действительно думал о третьем способе, которым я еще не уделил так много внимания. У меня мог быть шаблонный класс обертки, который добавляется к дереву вместо этого, которое позволяет мне, возможно, называть свободные функции для выполнения безотносительно действий, таким образом, я предполагаю, поскольку оно действует как движение между для узлов и интерфейса:

(псевдо код первое, что пришло на ум только для давания общее представление):

template <class T>
TreeNode(T &modelNode)
{
    m_modelNode = modelNode;
}

template <>
void TreeNode<AreaNode>::editClickedEvent()
{
    openEditDialog(m_modelNode); // Called with concrete AreaNode
}

template <>
void TreeNode<LocationNode>::editClickedEvent()
{
    openEditDialog(m_modelNode); // Called with concrete LocationNode
}

и т.д.

Таким образом, это эффективно расширяет узлы, но по-другому к использованию посетителя и это кажется немного более опрятным.

Теперь, прежде чем я иду вперед и делаю решающий шаг с помощью одного из этих методов, я думал, что будет мудро получить некоторый вход.

Спасибо! Я надеюсь, что все это имеет некоторый смысл..

Править:

Я копировал шаблонную идею обертки..

class INode
{
public:
    virtual ~INode() {}
    virtual void foo() = 0;
};

class AreaNode : public INode
{
public:
    AreaNode() {}
    virtual ~AreaNode() {}
    void foo() { printf("AreaNode::foo\r\n"); }
};

class RoleNode : public INode
{
public:
    RoleNode() {}
    virtual ~RoleNode() {}
    void foo() { printf("RoleNode::foo\r\n"); }
};

class ITreeNode
{
public:
    virtual ~ITreeNode() {}
    virtual void bar() = 0;
    virtual void foo() = 0;
};

template <class T>
class MainViewTreeNode : public ITreeNode
{
public:
    MainViewTreeNode() : m_node() {}
    virtual ~MainViewTreeNode() {}
    void bar() {}
    void foo() { m_node.foo(); }
protected:
    T m_node;
};

template <>
void MainViewTreeNode<AreaNode>::bar()
{
    printf("MainViewTreeNode<AreaNode>::bar\r\n");
}

template <>
void MainViewTreeNode<RoleNode>::bar()
{
    printf("MainViewTreeNode<RoleNode>::bar\r\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
    MainViewTreeNode<RoleNode> role;
    MainViewTreeNode<AreaNode> area;

    std::list<ITreeNode*> nodes;
    nodes.push_back(&role);
    nodes.push_back(&area);

    std::list<ITreeNode*>::iterator it = nodes.begin();

    for (; it != nodes.end(); ++it)
    {
        (*it)->foo();
        (*it)->bar();
    }

    getchar();
    return 0;
}

Спасибо.

6
задан Mark 25 July 2010 в 20:13
поделиться