From GoF to Lambdas – The Command Pattern

Last year, Mario Fusco wrote a blog post series questioning the way Java developers are implementing the Gang of Four (GoF) patterns. He shared a functional approach, which is easier to read and maintain.

I will do my best to provide a C# version of Mario’s recommendations expanding some examples. Let’s start with the Command pattern.

The Command Pattern – how it is commonly adopted today

The Command Pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time.

In Java, this is commonly implemented defining an interface:

interface Command {
    void run();
}

At this point, the developer can provide different command implementations.

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

The “consumer” does not have to know about the details of the command execution. Some implementations will just affect the application state, other could save data on disk, for example.

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

In some cases, commands could be used to coordinate work with another components/applications.

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

It is a good practice to have something to coordinate the execution of one or more instances of this commands.

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

Finally it is possible to create a list of the commands we want to run

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

Commands, implemented in this way, are just functions wrapped into objects.

The Command Pattern – Mario’s recommendation

The FunctionalInterface concept could make the Command pattern implementation a lot less verbose.

@FunctionalInterface
interface Command {
    void run();
}

If you are not familiar with the @FunctionalInterface annotation, they are used with Single Abstract Method interfaces – like Command. Functional interfaces can be represented with a simple lambda expression or a method reference. Java already provides a functional interface with a run method named Runnable

More natural than creating a class wrapping a single function is to write just that single function, right?

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

We don’t need an Executor class as well:

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

And all the commands could be executed just as before.

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

Mario explains:

Here the Java compiler automatically translates the lambdas with no arguments and invoking the void static methods executing the actions formerly wrapped in commands into anonymous implementation of the Runnable interface thus allowing to collect them in a List of Runnables.

Mario’s recommendation translated to C#

Now, it is time to apply Mario’s recommendation using C#. Let’s go!

First of all, we don’t need to create an interface. We don’t need to check if the BCL provides an interface neither. We have delegates!

public delegate void Command();

Here we are defining a delegate, but we could use Action with no prejudice.

We can use simple methods just like Mario did.

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

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

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

We can also execute it easily:

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

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

In a more “functional” approach, we could convert are functions into HOF.

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

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

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

This could be a good idea, especially if we want to perform some complex setup. Anyway, it removes the need of using lambdas when creating a command list.

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

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

We don’t need to create a class to implement the command pattern. There are simpler alternatives in Java *and* in C#.

Next time, let’s talk about the strategy pattern.

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:

O que mais me agrada no C4 Model é a forma como detalhes vão sendo explicitados na medida em que...
Confesso que estava sentindo falta de escrever em primeira pessoa. Há tempos, publicando apenas nos sites da EximiaCo, não encontrava,...
When you think about Roslyn source code, you should think about performance-oriented design. I would like to share some performance techniques...
Neste post, compartilho um exemplo de implementação para um algoritmo extremamente famoso e importante: O algoritmo de Dijkstra. Trata-se de...
Last post, I asked an explanation about the execution result of the following code. using System; using System.Threading.Tasks; using static...
07 de julho de 2016, aproximadamente 8:30 – Eu iria palestrar no TDC de São Paulo naquele dia. Aterrizamos em...

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.

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?