Es gibt verschiedene Möglichkeiten, wie ich komplexe Objekte initialisieren kann (mit eingefügten Abhängigkeiten und der erforderlichen Konfiguration von injizierten Membern), alle scheinen vernünftig zu sein, haben aber verschiedene Vor- und Nachteile. Ich werde ein konkretes Beispiel:Ist es eine gute oder schlechte Methode, Instanzmethoden von einem Java-Konstruktor aufzurufen?
final class MyClass {
private final Dependency dependency;
@Inject public MyClass(Dependency dependency) {
this.dependency = dependency;
dependency.addHandler(new Handler() {
@Override void handle(int foo) { MyClass.this.doSomething(foo); }
});
doSomething(0);
}
private void doSomething(int foo) { dependency.doSomethingElse(foo+1); }
}
Wie Sie sehen können, der Konstruktor tut 3 Dinge, eine Instanz Methode einschließlich Aufruf. Mir wurde gesagt, dass das Aufrufen von Instanzmethoden aus einem Konstruktor unsicher ist, da es die Prüfungen des Compilers für nicht initialisierte Member umgeht. I.e. Ich hätte doSomething(0)
vor der Einstellung this.dependency
aufrufen können, die kompiliert hätte aber nicht funktioniert. Was ist der beste Weg, dies zu überdenken?
Make
doSomething
statisch und übergeben Sie die Abhängigkeit explizit? In meinem tatsächlichen Fall habe ich drei Instanzmethoden und drei Mitgliedsfelder, die alle voneinander abhängig sind, so dass dies wie eine Menge zusätzlicher Vorkehrungen erscheint, um alle drei davon statisch zu machen.Verschieben Sie die
addHandler
unddoSomething
in eine@Inject public void init()
Methode. Während die Verwendung mit Guice transparent sein wird, erfordert es eine manuelle Konstruktion, um sicher zu sein,init()
zu rufen, sonst ist das Objekt nicht voll funktionsfähig, wenn jemand es vergisst. Dies macht auch mehr von der API frei, die beide wie schlechte Ideen erscheinen.Wrap eine verschachtelte Klasse, um die Abhängigkeit zu halten, dass es ohne auszusetzen zusätzliche API richtig zu machen verhält:
class DependencyManager { private final Dependency dependency; public DependecyManager(Dependency dependency) { ... } public doSomething(int foo) { ... } } @Inject public MyClass(Dependency dependency) { DependencyManager manager = new DependencyManager(dependency); manager.doSomething(0); }
Dies zieht aus allen Konstrukteuren Instanzmethoden, sondern eine zusätzliche Schicht von Klassen erzeugt, und wenn ich hatte schon inner und anonyme Klassen (zB der Handler) kann verwirrend werden - als ich das versuchte, wurde mir gesagt, ich solle dieDependencyManager
in eine separate Datei verschieben, was auch geschmacklos ist, weil es jetzt mehrere Dateien gibt, um eine einzige Sache zu machen.
Also, was ist der bevorzugte Weg, um mit dieser Art von Situation umzugehen?
@Steve: Ich habe nur die ersten "Pre" -Tags entfernt, so dass der Code farbcodierte Syntax zeigt :) – SyntaxT3rr0r
Cool, wusste nicht, dass es so funktioniert. – Steve