Существует ли шаблон проектирования или базовый объектно-ориентированный принцип, который касается этого случая общих ресурсов?

Допустим, у меня есть три класса, Solid, Face, а также Edge которые определены следующим образом:

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 управляет «надмножеством» Edges. каждый Face тот Solid управляет будет иметь «подмножество» Solid.edges, Далее любые два Solid.faces может иметь общее Edge,

Мой вопрос: есть ли шаблоны проектирования или общие объектно-ориентированные принципы для решения подобных ситуаций? Как я могу управлять отношениями между Solid.edges а также Face.edges? Более конкретно

3

Решение

Существует много способов управления такими видами отношений, но если вы хотите повысить эффективность и хотите разделить вершины между ребрами и разделить ребра между гранями, тогда я предлагаю Solid должен иметь полный список Vertex а также Edges,

затем 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 за Edge а также Vertex но тогда вам придется заплатить за динамическое распределение памяти и более плохую локальность данных.

Заманчиво хранить обратную ссылку на Solid внутри Face а также Edge для лучшей инкапсуляции. Вы могли бы сделать это, но тогда vector из Face а также Edge эффективно содержать много повторяющихся указателей. Если такой вид инкапсуляции важен для вас, я предлагаю вам создать классы-оболочки для работы с ребрами и гранями, которые содержат необработанный объект ребра / грани, а также обратную ссылку на Solid,

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]