Nos últimos meses, tropecei algumas vezes na seguinte técnica / padrão. No entanto, não consigo encontrar um nome específico, nem tenho 100% de certeza sobre todas as suas vantagens e desvantagens.
O padrão é o seguinte:
Dentro de uma interface Java, um conjunto de métodos comuns é definido como de costume. No entanto, usando uma classe interna, uma instância padrão vaza pela interface.
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
}
}
}
Para mim, parece que a maior vantagem está no fato de que um desenvolvedor precisa apenas conhecer a interface e não suas implementações, por exemplo, caso ele queira criar rapidamente uma instância.
Vehicle someVehicle = Vehicle.Default.getInstance();
someVehicle.accelerate();
Além disso, vi essa técnica sendo usada junto com o Spring para fornecer instâncias dinamicamente, dependendo da configuração. Nesse sentido, também parece que isso pode ajudar na modularização.
No entanto, não posso deixar de pensar que isso é um uso indevido da interface, pois ela acopla a interface a uma de suas implementações. (Princípio de inversão de dependência etc.) Alguém poderia me explicar como é chamada essa técnica, bem como suas vantagens e desvantagens?
Atualizar:
Após algum tempo para consideração, verifiquei novamente e notei que a seguinte versão singleton do padrão era usada com muito mais frequência. Nesta versão, uma instância estática pública é exposta através da interface que é inicializada apenas uma vez (devido ao campo ser final). Além disso, a instância é quase sempre recuperada usando o Spring ou uma fábrica genérica que desacopla a interface da implementação.
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;
Em poucas palavras: parece que esse é um padrão singleton / factory personalizado, que basicamente permite expor uma instância ou singleton por meio de sua interface. Com relação às desvantagens, algumas foram citadas nas respostas e comentários abaixo. Até agora, a vantagem parece estar na sua conveniência.
Vehicle.Default
deve ser movido para o namespace do pacote como uma classe de fábrica, por exemplo VehicleFactory
.
Vehicle.Default.getInstance() != Vehicle.Default.getInstance()