Riepilogo: Perché è sbagliato progettare un costruttore solo per i suoi effetti collaterali e quindi utilizzare il costruttore senza assegnare mai il suo valore di ritorno a una variabile?
Sto lavorando a un progetto che prevede la modellazione di giochi di carte. L'API pubblica per il gioco utilizza uno schema dispari per istanziare oggetti Rank e Suit. Entrambi utilizzano un elenco statico per tenere traccia delle istanze. In un mazzo standard, ci saranno sempre solo quattro oggetti Suit e tredici Classifica. Quando costruisci una carta, i ranghi e le tute si ottengono con una getRank()
statica e una getSuit()
, che restituisce l'oggetto identificato dall'elenco statico. Rank e Suit hanno altri metodi statici come removeRank()
e clear()
.
Ciò che è strano è che non esiste un metodo statico add()
per aggiungere un nuovo Rank o Suit alla lista statica. Invece, questo comportamento si verifica solo quando un costruttore Rank o Suit viene invocato tramite new
. Poiché le istanze di Rank e Suit sono ottenute con lo statico getRank()
, il valore restituito dai nuovi costruttori è completamente irrilevante.
Alcuni codice di esempio potrebbe assomigliare a questo
//set up the standard suits
Suit.clear(); //remove all Suit instances from the static list
new Suit("clubs", 0); //add a new instance, throw away the returned value
new Suit("diamonds", 1);
new Suit("hearts", 2);
new Suit("spades", 3);
//create a card
Deck theDeck = new Deck()
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 13; j++) {
Suit theSuit = Suit.getSuit(i);
Rank theRank = Rank.getRank(j);
theDeck.add(new Card(theSuit, theRank));
}
}
Non ho mai visto codice che non assegni l'oggetto restituito da un costruttore. Non pensavo nemmeno che fosse possibile farlo in Java fino a quando non l'ho testato. Tuttavia, quando è stato sollevato il problema che mancava il metodo statico addSuit()
, la risposta era
"Objects of type Suit and Rank are created via constructors. The intent is to mimic the behavior of the java.lang.Enum class in which objects are created via constructors and the class maintains the collection of such objects. Current behavior is designed as intended."
L'uso di costruttori in questo modo mi fa davvero male, e voglio riaprire il problema, ma non riesco a trovare molto materiale a supporto (linee guida per la codifica, anti-pattern, altra documentazione). Si tratta in realtà di uno schema di codifica valido che non ho mai incontrato prima? In caso contrario, quale è un buon argomento che posso fare per far cambiare l'API?
Questo è un articolo che parla di ciò che i costruttori dovrebbero fare:
We can agree that a constructor always needs to initialize new instances, and we might even agree by now that a constructor always needs initialize instances completely.
Le modifiche: Aggiunte informazioni aggiuntive sulla risposta del progettista al problema. Aggiunti alcuni articoli che parlano di ciò che i costruttori dovrebbero e non dovrebbero fare.