Ho un problema e voglio sapere qual è il modo migliore per risolverlo.
Problema:
Ho un albero delle decisioni binarie . Ogni nodo foglia ha un oggetto (chiamato Matrix ) che memorizza alcune informazioni ed esegue alcuni calcoli. Ad un certo punto durante l'esecuzione, voglio chiedere a Matrix se dovrei dividere il nodo foglia. Se sì, dovrei creare due bambini ognuno ha la sua matrice e dovrei eliminare la matrice del nodo corrente (perché non è più una foglia). Esistono due tipi di matrici, ma tutti i nodi foglia usano lo stesso tipo.
interface Matrix {}
class MatrixA extends Matrix {}
class MatrixB extends Matrix {}
Ho trovato diversi approcci per risolvere questo problema, ma non so quale sia il migliore.
Design # 1:
class Node {
Node left, right;
Matrix mat;
MatrixFactory fact;
Node(MatrixFactory fact) {
this.fact = fact;
this.mat = fact.newMatrix();
}
void split() {
if (mat.isSplitNeeded()) {
this.mat = null;
this.left = Node(this.fact);
this.right = Node(this.fact);
}
}
}
Il problema è che, mi sembra di violare Principio di responsabilità singola , perché il nodo è responsabile della struttura dell'albero, della gestione della matrice e della divisione.
Design # 2:
class Node {
Node left, right;
}
class NodeMatrixManager {
Map<Node, Matrix> map;
MatrixFactory fact;
NodeMatrixManager(MatrixFactory fact) {
this.fact = fact;
}
void split(Node node) {
mat = this.map[node];
if (mat.isSplitNeeded()) {
node.left = Node();
node.right = Node();
this.map.remove(node);
this.map.insert(new Pair(node.left, this.fact.newMatrix()));
this.map.insert(new Pair(node.right, this.fact.newMatrix()));
}
}
}
Ancora una volta ritengo di violare Principio di responsabilità singola , poiché NodeMatrixManager è responsabile sia della tracciabilità della relazione Matrix-Node, sia della suddivisione.
Design # 3:
class Node {
Node left, right;
}
class NodeMatrixManager {
Map<Node, Matrix> map;
Matrix getMat(Node node) {return this.map[node];}
insert(Node node, Matrix mat) {this.map.insert(new Pair(node, mat));}
remove(Node node) {this.map.remove(node);}
}
class Splitter {
NodeMatrixManager manager;
MatrixFactory fact;
Splitter(NodeMatrixManager manager, MatrixFactory fact) {
this.manager = manager;
this.fact = fact;
}
void split(Node node) {
mat = this.manager.getMat(node);
if (mat.isSplitNeeded()) {
node.left = Node();
node.right = Node();
this.manager.remove(node);
this.manager.insert(node.left, this.fact.newMatrix());
this.manager.insert(node.right, this.fact.newMatrix());
}
}
}
In questo approccio sento che la classe NodeMatrixManager non è necessaria, perché ho separato Matrix dal nodo in modo che il nodo non abbia troppa responsabilità e ora Splitter ha tutte le responsabilità. Quindi, perché non rimettere semplicemente Matrix nel nodo ed evitare la mappatura non necessaria?
Design # 4:
class Node {
Node left, right;
Matrix mat;
Node(Matrix mat) {this.mat = mat;}
}
class Splitter {
MatrixFactory fact;
Splitter(MatrixFactory fact) {
this.fact = fact;
}
void split(Node node) {
if (node.mat.isSplitNeeded()) {
node.mat = null;
node.left = Node(this.fact.newMatrix());
node.right = Node(this.fact.newMatrix());
}
}
}
Il mio problema con questo disegno è che una classe (Splitter) sta accedendo e manipolando le informazioni memorizzate in un'altra classe (Nodo). Non sembra corretto. Se metto la divisione di nuovo in classe Node, sono tornato dove ho iniziato.
Quindi qual è il miglior approccio al design? (scusa per la lunga domanda)