Olá, Fabiano. Como vai?
Excelente implementação! O seu código demonstra de forma muito limpa e prática o verdadeiro poder do Polimorfismo de Subtipos e o uso de interfaces no C#.
Ao criar a interface IAcaoBotao, você estabeleceu um contrato que garante que qualquer classe que a implemente possua o método Executar(). Isso permitiu que, na classe Program, você tratasse objetos de tipos totalmente diferentes (SalvarAcao, EditarAcao, ExcluirAcao) como se fossem do mesmo tipo genérico dentro da lista List<IAcaoBotao>.
Vantagens da sua Abordagem (Clean Code e Extensibilidade)
O grande trunfo da sua estrutura é o respeito ao princípio do Open/Closed Principle (Princípio do Aberto/Fechado). Se amanhã o sistema precisar de um novo botão, como "ImprimirRelatorioAcao", você não precisará alterar a estrutura do seu loop principal ou colocar blocos cheios de if/else ou switch/case.
Bastará criar a nova classe implementando a interface:
internal class ImprimirAcao : IAcaoBotao
{
public void Executar()
{
Console.WriteLine("Enviando documento para a impressora...");
}
}
E depois, apenas adicioná-la na sua lista na classe Program. O loop foreach continuará funcionando perfeitamente sem saber os detalhes internos de como a impressão é feita.
Uma Pequena Dica de Sintaxe sobre Interfaces em C#
O seu código está perfeito e roda sem problemas nas versões modernas do C#. Apenas como curiosidade técnica de boas práticas, ao declarar métodos dentro de uma interface:
internal interface IAcaoBotao
{
public void Executar();
}
Historicamente, os métodos de uma interface em C# são implicitamente públicos. Por isso, a maior parte da comunidade e dos guias de estilo costuma omitir o modificador public na assinatura do método dentro da interface, deixando apenas assim:
internal interface IAcaoBotao
{
void Executar(); // Implicitamente público
}
(Nas classes que implementam a interface, como SalvarAcao, o uso do public continua sendo obrigatório).
Parabéns pelo projeto e pela organização dos namespaces. O entendimento desse conceito é um divisor de águas para criar arquiteturas de sistemas robustas, como padrões de projeto (Design Patterns) como o Command ou Strategy.
Espero que possa ter lhe ajudado!