我被设计问题卡住了。我想不出任何好的解决办法。下面是问题说明。
我有一组设备,每一个设备都有一些共同的属性和行为。每个设备可以包含一个或多个其他类型的设备连接到它。例如:如果有4组设备A,B,C,D和A是所有设备的根。
A will have one or many B devices.
B will have one or many C devices.
C will have one or many D devices.
所有这些不同的设备都有一些共同的属性,而有些则是它们自己独有的。
I have to create a report which will read the data from these objects and read it to file. Report is in XML format and will depict hierarchy of whole system.
我该如何解决这个问题?任何建议和评论都将大有帮助。
这听起来像是访问者模式的一个例子。让访问者访问A
的每个子节点。对于每个子节点,它将再次访问所有子节点,以此类推。
当Visitor遍历树时,收集每个节点的数据。例如,在这种情况下,如果您愿意,可以直接在XML中收集数据。
访问者模式可以很好地处理异构数据类型,但是当一些节点也具有公共结构时也可以。
访问者模式是一种更好的执行操作的方式,所有的父类和子类都应该被接受作为输入,其中的行为由对象类型决定。
这里是c++实现供参考:
#include <vector>
#include <iostream>
using namespace std;
class Visitor
{
public:
virtual void visit(class Node *, class Common*) = 0;
virtual void visit(class CompositeNode *, Common*) = 0;
};
class Common
{
int value;
public:
Common(int val)
{
value = val;
}
virtual void traverse()
{
cout << value << " | ";
}
virtual void accept(Visitor &, Common*) = 0;
};
class Node: public Common
{
public:
Node(int val): Common(val){}
virtual void accept(Visitor &v, Common *c)
{
v.visit(this, c);
}
};
class CompositeNode: public Common
{
vector < Common * > children;
public:
CompositeNode(int val): Common(val){}
void add(Common *ele)
{
children.push_back(ele);
}
virtual void accept(Visitor &v, Common *c)
{
v.visit(this, c);
}
virtual void traverse()
{
Common::traverse();
for (int i = 0; i < children.size(); i++)
children[i]->traverse();
}
};
class AddVisitor: public Visitor
{
public:
virtual void visit(Node *, Common*)
{
}
virtual void visit(CompositeNode *node, Common *c)
{
node->add(c);
}
};
int main()
{
Common *nodes[3];
nodes[0] = new CompositeNode(0); //Consider A
nodes[1] = new CompositeNode(1); //Consider B
nodes[2] = new CompositeNode(2); //Consider B
AddVisitor addVisitor;
nodes[0]->accept(addVisitor, nodes[1]); //B
nodes[0]->accept(addVisitor, nodes[2]); //B
nodes[1]->accept(addVisitor, new Node(3)); //Consider C
nodes[1]->accept(addVisitor, new Node(4)); //Consider C
nodes[2]->accept(addVisitor, new Node(5)); //Consider C
nodes[2]->accept(addVisitor, new Node(6)); //Consider C
for (int i = 0; i < 3; i++)
{
cout<<"--------------------------------"<<endl;
nodes[i]->traverse();
cout<<endl;
}
}
--------------------------------
0 | 1 | 3 | 4 | 2 | 5 | 6 |
--------------------------------
1 | 3 | 4 |
--------------------------------
2 | 5 | 6 |