Tôi có giao diện người dùng với chế độ xem dạng cây ở bên trái và trình xem bên phải (giống như ứng dụng email). Người xem ở bên phải hiển thị chi tiết của bất cứ điều gì tôi đã chọn trong cây bên trái.Cách tốt nhất để thực hiện các thao tác trên các nút cây, tốt nhất là không sử dụng các khách truy cập
Giao diện người dùng có các nút "thêm", "chỉnh sửa" và "xóa". Các nút này hoạt động khác nhau tùy thuộc vào "nút" trong cây được chọn.
Nếu tôi có nút của một loại cụ thể được chọn và người dùng nhấp vào "chỉnh sửa", thì tôi cần mở hộp thoại chỉnh sửa thích hợp cho loại nút cụ thể đó, với chi tiết của nút đó.
Bây giờ, có rất nhiều loại nút khác nhau và triển khai lớp khách truy cập cảm thấy hơi lộn xộn (hiện tại khách truy cập của tôi có khoảng 48 mục ....). Nó hoạt động độc đáo mặc dù - về cơ bản để chỉnh sửa một cái gì đó giống như một lớp OpenEditDialog kế thừa khách truy cập và mở hộp thoại chỉnh sửa thích hợp:
abstractTreeNode-> accept (OpenEditDialog());
Vấn đề là tôi phải triển khai lớp khách truy cập trừu tượng cho mọi "hành động" mà tôi muốn thực hiện trên nút và vì một lý do nào đó tôi không thể không nghĩ rằng mình thiếu một mẹo.
Một cách khác có thể của từng để thực hiện các chức năng trong các nút tự:
abstractTreeNode->openEditDialog();
Tôi Ording nút xung quanh một chút ở đây, vì vậy có lẽ đây là tốt hơn:
abstractTreeNode->editClickedEvent();
Tôi không thể không nghĩ rằng điều này là gây ô nhiễm các nút mặc dù.
Tôi đã nghĩ ra cách thứ ba mà tôi chưa đưa ra nhiều suy nghĩ. Tôi có thể có một lớp wrapper templated được thêm vào cây thay vì cho phép tôi có thể gọi miễn phí-chức năng để thực hiện bất kỳ hành động, vì vậy tôi đoán vì nó hoạt động như một đi giữa các nút và giao diện:
(pseudo code ra khỏi đỉnh đầu của tôi chỉ đưa ra một ý tưởng):
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
}
vv ..
Vì vậy, đây được mở rộng một cách hiệu quả các nút nhưng theo một cách khác nhau để sử dụng khách truy cập và có vẻ như một chút gọn gàng .
Bây giờ trước khi tôi tiếp tục và thực hiện việc sử dụng một trong các phương pháp này, tôi nghĩ sẽ rất khôn ngoan để có được một số đầu vào.
Cảm ơn! Tôi hy vọng tất cả điều này làm cho một số ý nghĩa ..
EDIT:
Tôi đã chế giễu lên ý tưởng wrapper templated ..
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;
}
Cảm ơn.
Ngay cả với một vài thao tác, mẫu Khách truy cập vẫn có thể cải thiện tách và mô đun của mã. – Thomas
chỉ để được rõ ràng, bạn có nghĩa là có lẽ trong trường hợp này chỉ cần thực hiện các chức năng trực tiếp trong các lớp nút? – Mark
@marksim: Vâng, đó là ý của tôi. OTOH, @Thomas không có điểm: Nó đan xen các hoạt động trên cây với dữ liệu của cây.Đưa dữ liệu và các hoạt động vào các đối tượng là những gì OOP là tất cả về, nhưng tôi không nghĩ rằng OOP là chén thánh. Nó có nhược điểm của nó. Cuối cùng, bạn là người duy nhất trong chúng tôi biết đủ về miền ứng dụng để có thể đưa ra quyết định sáng suốt. Chúng tôi chỉ có thể gợi ý các giải pháp khả thi. – sbi