Os nomes têm a oportunidade de transmitir significado. Por que você jogaria fora essa oportunidade com o Impl?
Primeiro de tudo, se você tiver apenas uma implementação, elimine a interface. Ele cria esse problema de nomenclatura e não adiciona nada. Pior ainda, pode causar problemas com assinaturas de método inconsistentes nas APIs se você e todos os outros desenvolvedores não tiverem o cuidado de sempre usar apenas a interface.
Dado isso, podemos assumir que toda interface possui ou pode ter duas ou mais implementações.
Se você possui apenas um agora e não sabe de que maneira o outro pode ser diferente, o padrão é um bom começo.
Se você tem dois agora, nomeie cada um de acordo com sua finalidade.
Exemplo: Recentemente, tivemos uma classe concreta Context (em referência a um banco de dados). Percebemos que precisávamos representar um contexto offline, portanto o nome Contexto foi usado para uma nova interface (para manter a compatibilidade com APIs antigas) e uma nova implementação foi criada, OfflineContext . Mas adivinhe como o original foi renomeado? É isso mesmo, ContextImpl (caramba).
Nesse caso, o DefaultContext provavelmente ficaria bem e as pessoas o receberiam, mas não é tão descritivo quanto poderia ser. Afinal, se não estiver offline , o que é? Então fomos com: OnlineContext .
Caso especial: Usando o prefixo "I" nas interfaces
Uma das outras respostas sugeridas usando o prefixo I nas interfaces. De preferência, você não precisa fazer isso.
No entanto, se você precisar de uma interface, para implementações personalizadas, mas também tiver uma implementação concreta primária que será usada com freqüência, e o nome básico para ela é simples demais para desistir de uma interface sozinha, considere adicionar "I" para a interface (no entanto, está tudo bem se ele ainda não estiver adequado para você e sua equipe).
Exemplo: Muitos objetos podem ser um "EventDispatcher". Por uma questão de APIs, isso deve estar em conformidade com uma interface. Mas você também deseja fornecer um distribuidor de eventos básico para delegação. DefaultEventDispatcher seria bom, mas é um pouco longo, e se você vir o nome com frequência, pode preferir usar o nome base EventDispatcher para a classe concreta e implementar o IEventDispatcher para implementações personalizadas:
/* Option 1, traditional verbose naming: */
interface EventDispatcher { /* interface for all event dispatchers */ }
class DefaultEventDispatcher implements EventDispatcher {
/* default event dispatcher */
}
/* Option 2, "I" abbreviation because "EventDispatcher" will be a common default: */
interface IEventDispatcher { /* interface for all event dispatchers */ }
class EventDispatcher implements IEventDispatcher {
/* default event dispatcher. */
}