Sono d'accordo con ciò che Christophe dice in la sua risposta . Una cosa che non posso ignorare è la tua richiesta di usare l'iniezione di dipendenza. Quello che stai facendo NON è affatto l'iniezione di dipendenza. Hai il tuo codice di costruzione (i metodi build
) mescolato con il tuo codice di comportamento (i metodi is
). Non c'è modo di ignorare questo codice di costruzione. Ciò rende il tuo codice difficile da modificare e difficile da testare. L'iniezione di dipendenza dice che dovresti chiedere ciò di cui hai bisogno, non cercare o costruire ciò di cui hai bisogno.
Ma se vuoi farlo, cosa penso che vuoi fare, il tuo problema fondamentale è che hai bisogno di una struttura dati diversa.
Ne ho uno che ti permetterà di fare questo:
public static void main(String[] args) {
WordCollection wc = new WordCollection(new MapOfSetsBuilder()
.add("prologue", "chapters")
.add("section", "chapters")
.add("epilogue", "chapters")
.add("chapter", "chapters")
.add("of", "prepositions")
.add("for", "prepositions")
.add("smurf", "chapters", "prepositions", "articles", "verbs", "adverbs", "nouns")
.build()
);
if (wc.word("prologue").isOfType("chapters")) {
System.out.println("Whoo Hoo!");
}
if (wc.word("smurf").isOfType("nouns")) {
System.out.println("Smurftastic!");
}
if (wc.word("smurf").isOfType("gargamel")) {
System.out.println("Noo! Why? This is so wrong.");
}
}
Uscite:
Whoo Hoo!
Smurftastic!
La struttura? Map<String, Set<String>>
Sto mappando ogni parola al suo tipo. Una parola potrebbe avere più di un tipo, quindi esegue il mapping su un insieme di tipi.
Tutto ciò che serve è questo:
//Construction class
class MapOfSetsBuilder {
Map<String, Set<String>> result = new HashMap<>();
public MapOfSetsBuilder add(String key, String... values) {
Set setForKey = new HashSet<String>();
setForKey.addAll(Arrays.asList(values));
result.put(key, setForKey );
return this;
}
public Map<String, Set<String>> build() {
return result;
}
}
//Behavior class
class WordCollection {
Map<String, Set<String>> categories;
WordCollection (Map<String, Set<String>> categories){
this.categories = categories;
}
public TypeTest word(String word) {
return new TypeTest(word);
}
class TypeTest {
String word;
TypeTest(String word) {
this.word = word;
}
Boolean isOfType(String category) {
return WordCollection.this.categories.get(word).contains(category);
}
}
}
I'm not wanting to build ever set every time I instantiate the class ...
OK ya pigro barbuto ecco come farlo senza scattare una iniezione di dipendenza adeguata in faccia:
//Behavior class
class WordCollection {
Map<String, Set<String>> categories;
WordCollection(Map<String, Set<String>> categories) {
this.categories = categories;
}
public TypeTest word(String word) {
return new TypeTest(word);
}
class TypeTest {
String word;
TypeTest(String word) {
this.word = word;
}
Boolean isOfType(String category) {
return WordCollection.this.categories.get(word).contains(category);
}
}
public static class Builder {
public WordCollection buildDefault() {
return new WordCollection(new MapOfSetsBuilder()
.add("prologue", "chapters")
.add("section", "chapters")
.add("epilogue", "chapters")
.add("chapter", "chapters")
.add("of", "prepositions")
.add("for", "prepositions")
.add("smurf","chapters","prepositions","articles","verbs","adverbs","nouns")
.build()
);
}
}
}
Piuttosto che un metodo factory statico che non può essere passato in giro come riferimento nella vera dipendenza, fasion injection ho optato per una classe builder interna statica. Questo ricorda il schema di costruzione di Josh Bloch ma è meno doloroso perché della classe MapOfSetsBuilder
che aiuta. Questo è invocato con:
WordCollection wc = new WordCollection.Builder().buildDefault();
Perché non un semplice metodo di fabbrica statico ? Perché sono su metodo statico che odia il kick . Non mi piace essere costretto ad uscire dalla modalità istanza quando non c'è una buona ragione a parte per la necessità di un po 'più di digitazione.
Ad ogni modo, questo ultimo bit non è necessario per l'iniezione di dipendenza. È solo una comodità. Non fa nulla che tu non abbia potuto fare in main e condiviso in giro. Il costruttore che prende la mappa è ciò che sta supportando l'iniezione di dipendenza qui. Fatto in questo modo, almeno il costruttore WordCollection
può ancora prendere qualsiasi mappa di set di stringhe. Non solo questa mappa predefinita.