Pelas suas perguntas me parece que ainda não lhe está claro o que é uma classe e o que é um objeto.
Você já reparou que o método getInstance() da classe BD é estático?
E ele inicializa um atributo estático do tipo BD somente se esse atributo ainda não foi inicializado.
Você pode ter trocentas variáveis bd espalhadas pelas suas classes, como eles são inicializadas através do método BD.getInstance(), elas vão referenciar o mesmo objeto, o mesmo endereço de memória, entende?
Tanto o endEntClientes quanto clientes possuem um atributo bd, porque você optou em fazer assim, só você pode responder.
Minha sugestão é usar sempre as variáveis do tipo BD como sendo variáveis locais.
Você não precisa acessar um atributo do endEntClientes é só você fazer isso:
BD.getInstance().close();
O atributo bd tanto do endEntClientes quanto do clientes referência o mesmo objeto retornado pelo BD.getInstance() então é indiferente qual bd você vai usar, eles são o mesmo objeto.
Recomendo você apagar o atributo bd dessas classes e utilizar somente variáveis locais.
Acho que você ainda não entendeu o que o getInstance() faz, sugiro que coloque os seguintes prints:
public static synchronized BD getInstance() {
if (instance == null) {
System.out.println("Criando objeto da classe BD");
instance = new BD();
}
System.out.println("Retornando objeto existente da classe BD");
return instance;
}
