是否有一种设计模式或面向对象的基本原则来处理这种共享资源的情况?



假设我有三个类,SolidFaceEdge,定义如下:

class Solid{
public:
// perform an action on a single edge.
void addFillet(int edgeNum);
// perform an action on a single face
void addBore(int faceNum);
// perform an action on all faces and edges
void move(Pos newPosition);
private:
std::vector<Edge*> edges;
std::vector<Face*> faces;
};
class Face{
public:
// will modify a subset of edges
virtual void changeHeight(int newHeight) = 0;
private:
int myNum;
std::vector<Edge> edges;
}
class Edge{
public:
virtual void changeLength(int newLength) = 0;
private:
int myNum;
int length;
}

在此示例中,Solid管理Edge的"超集"。Solid管理的每个Face都将具有Solid.edges的"子集"。此外,任何两个Solid.faces都可以具有共同的Edge

我的问题是:是否有任何设计模式或一般面向对象原则来处理这种情况?如何管理Solid.edgesFace.edges之间的关系?更具体地说

有很多方法可以管理这些类型的关系,但是如果您想要效率并且想要在边之间共享顶点并在面之间共享边,那么我建议您的Solid应该拥有完整的VertexEdges列表。

然后Edge对其顶点有某种非拥有的引用,Face对其边有某种非拥有的引用。那些非拥有引用可能类似于指针,但您必须小心不要通过重新分配顶点或边的主列表来使这些指针无效。如果改为存储索引会更安全。但这确实意味着您必须参考Solid才能找出顶点/边索引所指的内容:

class Solid {
std::vector<Vertex> vertices;
std::vector<Edge> edges;
std::vector<Face> faces;
public:
Solid(std::vector<Vertex> vertices) : vertices(std::move(vertices)) {}
void addEdge(int vertex_index1, int vertex_index2) {
edges.emplace_back(vertex_index1, vertex_index2);
}
void addFace(std::vector<int> edge_indices) {
faces.emplace_back(std::move(edge_indices));
}
const Vertex &getVertex(int vertex_index) const { return vertices[vertex_index]; }
const Edge &getEdge(int edge_index) const { return edges[edge_index]; }
};
class Edge {
int vertex_first;
int vertex_second;
public:
Edge(int vertex_first, int vertex_second)
: vertex_first(vertex_first), vertex_second(vertex_second) {}
const Vertex &getVertexFirst(const Solid &solid) const {
return solid.getVertex(vertex_first);
}
const Vertex &getVertexSecond(const Solid &solid) const {
return solid.getVertex(vertex_second);
}
};
class Face {
std::vector<int> edge_indices;
int getEdgeIndex(int face_edge_index) const {
return edge_indices[face_edge_index];
}
public:
Face(std::vector<int> edge_indices) : edge_indices(std::move(edge_indices)) {}
const Edge &getEdge(int face_edge_index, const Solid &solid) const {
return solid.getEdge(getEdgeIndex(face_edge_index));
}
};

现场演示。

另一种方法是将std::shared_ptr用于EdgeVertex但随后您必须为动态内存分配和较差的数据局部性付费。

Face内部存储对Solid的反向引用是很诱人的,Edge以便更好地封装。你可以这样做,但FaceEdgevector有效地包含大量重复的指针。如果这种封装对您很重要,我建议您创建某种包装类来处理包含原始边缘/面对象的边缘和面以及对Solid的反向引用。

最新更新