Non sono d'accordo con la saggezza generalmente accettata che le classi di utilità dovrebbero essere evitate. Usando Java qui come esempio, ma sono sicuro che l'idea si applica anche ad altre lingue.
Considera, ad esempio, un tipo di dati di cui hai bisogno sia delle varianti mutabili (per le prestazioni) che immutabili (per hash table, set, altri tipi di problemi di correttezza, ecc.): un numero complesso. Quindi, hai Complex
(immutabile) e ComplexBuffer
(mutabile). Ora sarebbe sciocco scrivere quattro versioni della sottrazione di sottrazione ( Complex
- Complex
, ComplexBuffer
- Complex
, Complex
- ComplexBuffer
, ComplexBuffer
- ComplexBuffer
), quindi vuoi creare un'interfaccia comune ComplexNumber
condivisa da Complex
e ComplexBuffer
. L'interfaccia ComplexNumber
ha metodi getReal()
e getImag()
.
Ora, per sottrarre due oggetti di implementazione di ComplexNumber
, definirai una classe ComplexUtils
e un metodo statico public static Complex sub(ComplexNumber, ComplexNumber)
. Quindi, ecco qui: un problema in cui la soluzione migliore è effettivamente utilizzare una classe di utilità. Ovviamente, per le prestazioni avrai anche ComplexBuffer.subInPlace(ComplexNumber)
che non crea assolutamente nuovi oggetti.
Quindi, non seguire ciecamente il consiglio che le classi di utilità dovrebbero essere evitate. Come ha detto John Carmack:
Sometimes, the elegant implementation is just a function. Not a method. Not a class. Not a framework. Just a function.