У меня есть пользовательский интерфейс со структурным видом слева и средство просмотра справа (немного как почтовый клиент). Средство просмотра на праве отображает деталь того, что я выбрал в дереве слева.
Пользовательский интерфейс имеет, "добавляют", "редактируют" и "удаляют" кнопки. Эти кнопки действуют по-другому в зависимости от того, какой "узел" в дереве выбран.
Если у меня есть узел конкретного типа, выбранного, и пользовательские щелчки "редактирование", то я должен открыть соответствующее диалоговое окно редактирования для того конкретного типа узла с деталями того узла.
Теперь, существует много различных типов узла, и реализация класса посетителя чувствует себя немного грязной (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;
}
Спасибо.