Implementação Funcional de Design Patterns – Command

Ano passado, Mario Fusco escreveu uma série de posts questionando a forma como programadores Java estão implementando os padrões de projeto definidos pelo GoF. Ele compartilhou uma abordagem funcional, mais simples de ler e de manter .

Eu vou fazer o meu melhor para criar uma versão C# das recomendações de Fusco expandindo alguns exemplos. Vamos começar com o padrão Command.

O padrão Command – como é frequentemente implementado

O padrão Command é um padrão de comportamento em que um objeto é utilizado para encapsular toda informação necessária para executar uma ação ou disparar um evento em um momento futuro.

Em Java, ele geralmente começa a ser implementado pela definição de uma interface:

interface Command {
    void run();
}

Com a interface definida, o programador pode prover diferentes implementações.

public class Logger implements Command {
    public final String message;
 
    public Logger( String message ) {
        this.message = message;
    }
 
    @Override
    public void run() {
        // ..
    }
}

O código que irá consumir o comando não precisa saber detalhes da execução do comando. Algumas implementações vão afetar apenas o estado da aplicação, outras podem salvar dados no disco, por exemplo.

public class FileSaver implements Command {
    public final String message;
 
    public FileSaver( String message ) {
        this.message = message;
    }
 
    @Override
    public void run() {
        // ..
    }
}

Em alguns casos, comandos podem ser utilizados para coordenar trabalho com outros componentes/aplicações.

public class Mailer implements Command {
    public final String message;
 
    public Mailer( String message ) {
        this.message = message;
    }
 
    @Override
    public void run() {
        // ..
    }
}

É uma boa prática ter algo que coordene a execução de uma ou mais instâncias.

public class Executor {
    public void execute(List<Command> tasks) {
        for (Command task : tasks) {
            task.run();
        }
    }
}

Assim, é possível criar uma lista de comandos que se deseja executar.

List<Command> tasks = new ArrayList<>();
tasks.add(new Logger( "Hi" ));
tasks.add(new FileSaver( "Cheers" ));
tasks.add(new Mailer( "Bye" ));
 
new Executor().execute( tasks );

Comandos, implementados desata forma, são apenas funções envolvidas em objetos.

O padrão Command – conforme recomendação de Fusco

O conceito de FunctionalInterface permite a implementação desse padrão de forma muito mais expressiva.

@FunctionalInterface
interface Command {
    void run();
}

Se você não é familiarizado com a anotação @FunctionalInterface, ela pode ser usada com interfaces que definem um único método abstrato – como a interface Command em nosso exemplo. Interfaces funcionais podem ser representadas com uma expressão lambda simples ou com uma referência para um método.

Java já oferece uma interface com o método run chamada Runnable

Mais natural que crair uma classe com uma única função, é escrever apenas esta função, certo?

public static void log(String message) {
    // ..
}
 
public static void save(String message) {
    // ..
}
 
public static void send(String message) {
    // ..
}

Também não é necessário escrever uma classe para coordenar a execução.

public static void execute(List<Runnable> tasks ) {
    tasks.forEach( Runnable::run );
}

E todos os comandos podem ser executados da mesma forma que antes.

List<Runnable> tasks = new ArrayList<>();
tasks.add(() -> log("Hi"));
tasks.add(() -> save("Cheers"));
tasks.add(() -> send("Bye"));
 
execute( tasks );

Fusco explica:

Aqui, o compilador Java automaticamente traduz as expressões Lambda sem parâmetros em classes anônimas que implementam a interface Runnable, o que permite que a lista de comandos seja armazenada em uma lista.

Recomendação de Fusco traduzida para C#

Agora é hora de implementar as recomendações de Mario Fusco em C#!

Primeiro, não precisamos criar uma interface. Também não precisamos verificar se a BCL provê uma interface adequada também. Podemos usar delegates!

public delegate void Command();

Estamos definindo um delegate, mas poderíamos usar uma Action.

Podemos escrever métodos simples, da mesma forma como Mario fez.

public static void Log(string message)
{
    // ..
}

public static void Save(string message)
{
    // ..
}

public static void Send(string message)
{
    // ..
}

Também podemos executar facilmente:

var commands = new List<Command>
{
    () => Log("Hi"),
    () => Save("Cheers"),
    () => Send("Bye")
};

commands.ForEach(command => command());

Em uma abordagem ainda mais funcional, podemos converter os comandos em HOF.

public static Command Log(string message)
    => () => { /* .. */ };

public static Command Save(string message)
    => () => { /* .. */ };

public static Command Send(string message)
    => () => { /* .. */ };

Esta pode ser uma boa ideia, especialmente se precisamos alguma configuração. De qualquer forma, isso remove a necessidade de usar Lmbdas para criar a lista de comandos.

var commands = new List<Command>
{
    Log("Hi"),
    Save("Cheers"),
    Send("Bye")
};

commands.ForEach(command => command());

Não precisamos criar uma classe para implementar o padrão Command. Há alternativas mais simples em Java e em C#

Em breve, vamos falar sobre o padrão Strategy.

Compartilhe este insight:

Elemar Júnior

Sou fundador e CEO da EximiaCo e atuo como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Elemar Júnior

Sou fundador e CEO da EximiaCo e atuo como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Mais insights para o seu negócio

Veja mais alguns estudos e reflexões que podem gerar alguns insights para o seu negócio:

Sou privilegiado. Há anos, em função do meu trabalho, tenho a oportunidade de viajar para fora do país. Recentemente, passei,...
Empresas modernas, com estilo de gestão diferente e resultados espetaculares, estão desafiando tudo o que sabemos sobre estratégia e execução....
Neste post mostro como implementar um EventBus, utilizando RabbitMQ, em C#. Este código ainda está em desenvolvimento. Em breve, uma...
I wrote this post in 2016. Unfortunately, I lost it when I “rebooted” my blog. Anyway, I have a good...
Compete ao arquiteto corporativo a responsabilidade de descrever, analisar e comunicar os diversos aspectos da arquitetura corporativa, bem como registrar...
In this post, I’m going to share with you one of the RavenDB 4 features that I like the most:...

Curso Reputação e Marketing Pessoal

Masterclasses

01

Introdução do curso

02

Por que sua “reputação” é importante?

03

Como você se apresenta?

04

Como você apresenta suas ideias?

05

Como usar Storytelling?

06

Você tem uma dor? Eu tenho o alívio!

07

Escrita efetiva para não escritores

08

Como aumentar (e manter) sua audiência?

09

Gatilhos! Gatilhos!

10

Triple Threat: Domine Produto, Embalagem e Distribuição

11

Estratégias Vencedoras: Desbloqueie o Poder da Teoria dos Jogos

12

Análise SWOT de sua marca pessoal

13

Soterrado por informações? Aprenda a fazer gestão do conhecimento pessoal, do jeito certo

14

Vendo além do óbvio com a Pentad de Burkle

15

Construindo Reputação através de Métricas: A Arte de Alinhar Expectativas com Lag e Lead Measures

16

A Tríade da Liderança: Navegando entre Líder, Liderado e Contexto no Mundo do Marketing Pessoal

17

Análise PESTEL para Marketing Pessoal

18

Canvas de Proposta de Valor para Marca Pessoal

19

Método OKR para Objetivos Pessoais

20

Análise de Competências de Gallup

21

Feedback 360 Graus para Autoavaliação

22

Modelo de Cinco Forças de Porter

23

Estratégia Blue Ocean para Diferenciação Pessoal

24

Análise de Tendências para Previsão de Mercado

25

Design Thinking para Inovação Pessoal

26

Metodologia Agile para Desenvolvimento Pessoal

27

Análise de Redes Sociais para Ampliar Conexões

Lições complementares

28

Apresentando-se do Jeito Certo

29

O mercado remunera raridade? Como evidenciar a sua?

30

O que pode estar te impedindo de ter sucesso

Recomendações de Leituras

31

Aprendendo a qualificar sua reputação do jeito certo

32

Quem é você?

33

Qual a sua “IDEIA”?

34

StoryTelling

35

Você tem uma dor? Eu tenho o alívio!

36

Escrita efetiva para não escritores

37

Gatilhos!

38

Triple Threat: Domine Produto, Embalagem e Distribuição

39

Estratégias Vencedoras: Desbloqueie o Poder da Teoria do Jogos

40

Análise SWOT de sua marca pessoal

Inscrição realizada com sucesso!

No dia da masterclass você receberá um e-mail com um link para acompanhar a aula ao vivo. Até lá!

A sua subscrição foi enviada com sucesso!

Aguarde, em breve entraremos em contato com você para lhe fornecer mais informações sobre como participar da mentoria.

Masterclass
15/07

Pare de dar a solução certa para o problema errado

Muita gente boa quebra a cabeça por dias tentando resolver o que não estava quebrado, simplesmente por tentar dar a resposta certa pro problema errado, mas precisa realmente ser assim?

Crie sua conta

Preencha os dados para iniciar o seu cadastro no plano anual do Clube de Estudos:

Crie sua conta

Preencha os dados para iniciar o seu cadastro no plano mensal do Clube de Estudos:

× Precisa de ajuda?