Como em muitas coisas, a abordagem correta depende do que você está tentando fazer para o botão específico e do que mais você está fazendo com a atividade.
A classe de atividade implementa a interface :
Essa é uma boa opção quando você tem apenas um tipo de tarefa a ser executada quando esse ouvinte é chamado. Um exemplo disso seria um formulário simples com vários campos e um botão salvar. Prefiro que meu ouvinte de eventos verifique a origem do evento para decidir o que realmente precisa ser feito. Sei que alguns podem dizer que isso é uma coisa de estilo, mas acredito que, ao não exigir que o ouvinte faça essa verificação, é mais fácil seguir o código, pois você saberá exatamente o que está sendo chamado para cada evento.
Uma classe diferente implementa a interface :
Como eu disse acima, prefiro essa opção para quando tiver vários itens que podem disparar o mesmo evento. Estendendo o exemplo acima, vamos adicionar um botão claro que também requer um ouvinte de clique. Crie um ouvinte que faça as ações de salvamento e um que faça as ações de limpeza. Cada ouvinte é adicionado apenas aos componentes que produzirão essa ação.
Esta implementação possui um benefício adicional que você pode utilizar se desejar. O benefício é que ele impede que outras classes acionem o evento dentro da sua classe de atividade. Como o método da interface deve ser público, qualquer pessoa com uma referência à classe pode disparar o evento. Se você deseja um controle refinado sobre quem pode fazer o que no aplicativo, uma classe separada impede que qualquer pessoa com uma referência à atividade faça com que seu formulário seja limpo ou salvo (ou potencialmente quebrar o código se o ouvinte estiver utilizando a fonte, mas não lidar com entrada incorreta).
Uma classe interna anônima implementa a interface :
Esta é realmente apenas uma maneira específica de construir a segunda opção de usar uma classe diferente como a implementação. Essa opção pode restringir ainda mais quem tem acesso para acionar o evento, pois ninguém mais pode criar uma instância da classe. No entanto, acho que o fator mais importante entre as duas opções é a quantidade de trabalho que está sendo feito. Limpar alguns campos de texto é uma operação simples e direta. No entanto, o processo de salvar o arquivo for pode envolver várias tarefas: você está validando a entrada (o que deveria estar fazendo), gravando em um banco de dados para armazenar os valores e acionando alguma ação pós-salvamento. Nesse caso, criar uma classe separada com seu próprio arquivo fornecerá uma divisão mais clara entre o formulário de entrada e o processamento de dados. Por sua vez, isso mantém o código do formulário em vez de um arquivo maior com várias classes internas aninhadas dentro.