W ciągu ostatnich kilku miesięcy potknąłem się kilka razy o następującą technikę / schemat. Nie mogę jednak znaleźć konkretnej nazwy, ani nie jestem w 100% pewien wszystkich jej zalet i wad.
Wzór wygląda następująco:
W interfejsie Java zestaw typowych metod jest definiowany jak zwykle. Jednak przy użyciu klasy wewnętrznej domyślna instancja przecieka przez interfejs.
public interface Vehicle {
public void accelerate();
public void decelerate();
public static class Default {
public static Vehicle getInstance() {
return new Car(); // or use Spring to retrieve an instance
}
}
}
Wydaje mi się, że największą zaletą jest to, że programista musi wiedzieć tylko o interfejsie, a nie o jego implementacjach, np. Na wypadek, gdyby szybko chciał utworzyć instancję.
Vehicle someVehicle = Vehicle.Default.getInstance();
someVehicle.accelerate();
Ponadto widziałem tę technikę stosowaną razem ze Springem w celu dynamicznego dostarczania instancji w zależności od konfiguracji. Pod tym względem wygląda również na to, że może to pomóc w modularyzacji.
Niemniej jednak nie mogę pozbyć się wrażenia, że jest to niewłaściwe użycie interfejsu, ponieważ łączy on interfejs z jedną z jego implementacji. (Zasada inwersji zależności itp.) Czy ktoś mógłby mi wyjaśnić, jak nazywa się ta technika, a także jej zalety i wady?
Aktualizacja:
Po pewnym czasie zastanowiłem się ponownie i zauważyłem, że następująca pojedyncza wersja wzorca była używana znacznie częściej. W tej wersji publiczna instancja statyczna jest udostępniana przez interfejs, który jest inicjowany tylko raz (ze względu na to, że pole jest ostateczne). Ponadto instancja jest prawie zawsze pobierana za pomocą Spring lub ogólnej fabryki, która oddziela interfejs od implementacji.
public interface Vehicle {
public void accelerate();
public void decelerate();
public static class Default {
public static final Vehicle INSTANCE = getInstance();
private static Vehicle getInstance() {
return new Car(); // or use Spring/factory here
}
}
}
// Which allows to retrieve a singleton instance using...
Vehicle someVehicle = Vehicle.Default.INSTANCE;
W skrócie: wydaje się, że jest to niestandardowy wzorzec singletonu / fabryki, który w zasadzie pozwala ujawnić instancję lub singleton poprzez interfejs. Jeśli chodzi o wady, kilka zostało wymienionych w odpowiedziach i komentarzach poniżej. Jak dotąd korzyść wydaje się polegać na wygodzie.
Vehicle.Default
powinien zostać przeniesiony do przestrzeni nazw pakietów jako klasa fabryczna, np VehicleFactory
.
Vehicle.Default.getInstance() != Vehicle.Default.getInstance()