Istnieje kilka różnych sposobów inicjowania złożonych obiektów (z wstrzykniętymi zależnościami i wymaganą konfiguracją wstrzykiwanych członków), wszystkie wydają się rozsądne, ale mają różne wady i zalety. Podam konkretny przykład:Czy dobrą lub złą praktyką jest wywoływanie metod instancji z konstruktora Java?
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); }
}
Jak widać, konstruktor robi 3 rzeczy, w tym wywołanie metody instancji. Powiedziano mi, że wywoływanie metod instancji z konstruktora jest niebezpieczne, ponieważ omija sprawdzenia kompilacji niezainicjowanych członków. To znaczy. Mogłem zadzwonić pod numer doSomething(0)
przed ustawieniem this.dependency
, który zostałby skompilowany, ale nie działał. Jaki jest najlepszy sposób, aby to zmienić?
Ustawić
doSomething
statycznie i przekazać zależność jawnie? W moim rzeczywistym przypadku mam trzy metody instancji i trzy pola członkowskie, które wszystkie od siebie zależą, więc wydaje się, że jest wiele dodatkowych elementów, aby wszystkie te trzy statyczne.Przenieś
addHandler
idoSomething
do metody@Inject public void init()
. Podczas gdy użycie z Guice będzie przezroczyste, wymaga ręcznej konstrukcji, aby zadzwonić pod numerinit()
, inaczej obiekt nie będzie w pełni funkcjonalny, jeśli ktoś zapomni. Ponadto ujawnia to więcej API, z których oba wydają się złymi pomysłami.Wrap zagnieżdżona klasa utrzymać zależność aby upewnić się, że zachowuje się poprawnie, bez narażania dodatkowe API:
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); }
To ciągnie instancji metod spośród wszystkich konstruktorów, ale generuje dodatkową warstwę klas, a kiedy już wewnętrzne i anonimowe klasy (np. ten handler) może to być mylące - kiedy próbowałem, powiedziano mi, aby przenieśćDependencyManager
do osobnego pliku, co jest również niesmaczne, ponieważ jest teraz wiele plików, aby zrobić jedną rzecz.
Jaki jest preferowany sposób radzenia sobie z tego rodzaju sytuacją?
@Steve: Właśnie usunąłem pierwsze znaczniki "pre", aby kod wyświetlał się za pomocą kolorowej składni :) – SyntaxT3rr0r
Fajnie, nie wiedziałem, że zadziałało w ten sposób. – Steve