Ho una classe incaricata di rispondere a un evento di input e forse di attivare un altro evento. Per decidere, ha diverse regole da controllare.
Sto provando a scappare da una classe simile alla seguente:
public class Translator {
public void maybeTranslate() {
if (!condition1 || !condition2 || !condition3) {
return;
}
// All rules have passed
translate();
}
}
Mi piacerebbe che questa classe sapesse che ha delle regole da passare, ma non conosce le implementazioni delle regole. Il mio tentativo era di trasformarlo in questo modo:
public class Translator {
private Rule[] rules;
public Translator (Rule[] rules) { this.rules = rules; }
public void maybeTranslate() {
for (Rule rule : rules) {
if (!rule.passes()) {
return;
}
}
translate();
}
}
dove Rule
ha questa interfaccia:
public interface Rule {
boolean passes();
}
Ecco il mio problema: ora ho una nuova regola che accetta un parametro. Il suo metodo passes
richiederebbe un parametro String
. Il mio fondamento è sbagliato con questo nuovo requisito? Non vedo come posso adattare questo modello per contenere regole con vari parametri.
Questo parametro indica la fonte dell'evento di input. Posso modificare maybeTranslate
per ricevere questo valore da chiunque lo chiami e cambiare l'interfaccia Rule
in boolean passes(String str)
. Solo ora, la maggior parte delle mie regole ha un parametro che non gli interessa.
Questo è nel contesto di un'app per Android, dove Translator
verrà istanziato su diversi frammenti.
UPDATE: alcune modifiche dalla mia domanda originale.
Questo Translator
verrà utilizzato su più schermi. C'è solo una schermata alla volta e ogni schermata può avere un diverso set di regole.
Invece di fare in modo che una regola assuma un parametro e agisca in modo diverso, ho creato più regole dipendenti dallo schermo (ScreenOneRule, ScreenTwoRule, ecc.).
Ora userei la classe in questo modo:
public class ScreenOne {
Translator translator;
public Screen(Translator translator) { ... }
public void onSomeEvent() { translator.maybeTranslate(); }
}
e vorrei creare il set di regole per ScreenOne nella mia configurazione IoC (questo è un tentativo di pseudo codice):
Rule[] screenOneRules = new Rule[] { SharedRule1, SharedRule2, ScreenOneRule1 }
ScreenOne screenOne = new Screen(new Translator(screenOneRules))
Questo risolve il mio problema, anche se mi sembra che il design non sia perfetto. Cosa succede se in seguito ottengo una regola che dipende da un valore noto solo dopo l'istanziazione dello schermo? Ad esempio, supponiamo che una regola debba conoscere le coordinate (x, y) di dove l'utente ha toccato sullo schermo per attivare onSomeEvent. Ho la sensazione che ScreenOne
avrebbe bisogno di costruire le regole stesse in onSomeEvent
. Penso che questo stia tornando alla mia domanda iniziale.
In tal caso, vorrei avere l'istanziazione delle regole da qualche altra parte. La soluzione è avere una fabbrica come questa?
public class RuleFactory {
public Rule[] getRulesForScreenOne(int x, int y, String anotherParameter) {
return new Rule[] { new SharedRule1(x, y), new SharedRule2(anotherParameter) };
}
}
public void onSomeEvent() {
Rule[] rules = RuleFactory.getRulesForScreenOne(x, y, str);
translator.maybeTranslate(rules);
}
A quel punto, Translator non riceverebbe regole nel suo costruttore. Non riesco a capirlo, ma mi sembra che l'implementazione della fabbrica non sia giusta. Qualcosa sul nome del metodo.