Attualmente ho tre classi e rispettive interfacce e rispettivi builder:
-
Albero : la struttura dei dati (implementata in
SimpleTree
) -
ProbabilityTree : è un
Tree
con funzionalità aggiunte per selezionare casualmente nodi figlio e per regolare la probabilità di selezione di un nodo (implementata inProbabilityTreeImpl
). -
DynamicTree : è un
ProbabilityTree
che crea dinamicamente nodi quando un nodo richiesto non esiste ancora.
Il codice cliente ha bisogno di Alberi che supportano sia la selezione casuale dei nodi, come fornita da ProbabilityTree
, sia la struttura che cresce dinamicamente quando vengono richiesti nodi ancora inesistenti, come previsto da DynamicTree
.
NOTA: Attualmente tutti e tre gli alberi sono immutabili dopo essere stati costruiti; per DynamicTree
questo significa che i clienti non possono aggiungere o rimuovere nodi, ma la struttura stessa può cambiare automaticamente.
NOTA: vedi Github gist con le cinque classi Java per il codice.
Ci sono almeno due problemi con questo design:
-
DynamicTree
è derivato daProbabilityTree
, mentre concepzionalmente queste due capacità non sono correlate (cioè ortogonali). - L'utilizzo dell'ereditarietà per l'aggiunta funzionale è spesso considerato "cattivo design" (correggimi se ho torto qui).
Un design alternativo sarebbe quello di disaccoppiare ProbabilityTree
e DynamicTree
usando qualcosa di simile al decoratore e / o al modello dell'adattatore. L'utilizzo del proxy dinamico di Java potrebbe consentire ai "decoratori" di estendere il interfaccia e che può decorare altri Tree
s con interfacce estese; cioè:.
TreeDecorator implements InvocationHandler, ... {
Tree adapted;
...
Object invoke(Method method, Object[] args) {
if( «this class can/should handle method» ) {
return method.invoke(this, args);
} else if ( «this.adapted can/should handle method» ){
return method.invoke(adapted, args);
}
};
}
Ancora una volta ci sono alcuni problemi:
- L'utilizzo di
Proxy
rende il codice più difficile da comprendere.
Che cosa devo fare? Utilizzare l'ereditarietà per estendere la funzionalità, utilizzare il proxy dinamico o qualcos'altro?