Design Pattern: Command

01_command_design_pattern

O Design Pattern Command tem como objetivo criar objetos que encapsulam uma solicitação para executar um objeto específico.

Em um primeiro momento pode parecer meio complicado de entender, mas o que o padrão se propõem a fazer é encapsular a chamada de um objeto para que quem execute a chamada não precisa conhecer sobre o objeto… Ahn? Ainda está díficil né, mas ele é fácil viu, para endendermos melhor vamos propor um exemplo, vamos criar um controle que irá abrir e fechar um portão, ele também terá a opção de desfazer a última ação, para isso vamos cria a interface Command, que será a base para todo o padrão, segue o código abaixo:

No código acima criamos a interface e definimos 2 “contratos”, isso significa que cada implementação concreta dessas interface necessáriamente terá que implementar esses dois métodos!

Vamos verificar agora a classe Portao, que possuí os método par abrir e fechar:

O método abrir() ao ser acionado mudado o estado do portão para ABERTO e é feito um log por meio do print, no método fechar() é mudado o estado para FECHADO e também feito um log, assim como no outro método, temos também o método toString() implementado.

Agora que entra em ação o Command, para que o nosso controle não tenha conhecimento da API do Portao vamos encapsular a chama para abrir o portão na classe AbrirPortaoCommand:

Para fechar o portão vamos fazer a mesma coisa agora na classe FecharPortaoCommand:

Em ambas implementaçõe os métodos execute() e o undo() executam uma ação do portão, cada um fazendo a chamada de seu proposito.

Eu também criei uma classe com o nome SemAcaoCommand que não executa nada, é apenas uma implementação fazia sem ação, segue o código abaixo:

Agora vamos criar a classe Controle que terá as chamadas dos Command‘s:

Podemos notar que as chamadas a classe Portao feitas pela classe Controle foram feitas sem que a classe Controle soubesse o que estava fazendo! Isso porque as chamadas estão encapsuladas no nossos Command, e o nosso controle apenas sabe que está executando uma tarefa, isso é bom que temos um controle totalmente desacoplado e poderiamos trocar as ações dos botões de abrir e fechar por outros Command! Agora vamos ver tudo isso funcionando, para isso implementei a classe MainPortaoCommand:

Nela fazemos algumas chamadas no nosso controle para abrir o portão, fechar ele e também para desfazermos uma última ação, vamos executar a classe MainPortaoCommand com o seguinte comando para vermos os outputs:

ceb@cezb-note:~$ cd ~/$WORKSPACE_HOME/java-designpatterns/designpattern-command
ceb@cezb-note:designpattern-command$ mvn exec:java -Dstart-class=br.com.batistao.MainControleDePonto

E teremos um resultado parecido com o mostrado abaixo:

...
[INFO] --- exec-maven-plugin:1.3.2:java (default-cli) @ designpattern-command ---
[WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
O portão da casa está fechado
O portão abriu...
O portão da casa está aberto
O portão fechou...
O portão da casa está fechado
O portão abriu...
O portão da casa está aberto
O portão fechou...
O portão da casa está fechado
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...

O legal desse padrão que podemos encapsular os Command e quem os chama nem faz ideia do que será executado!

Definindo o Pattern Command:

O Pattern Command encapsula uma solicitação como um objeto, o que permite parametrizar outros objetos com diferentes solicitações, enfileirando, registrando solicitações e implementando recursos de cancelamento de operações.

02_diagrama_classe_command

Nota: Todo o código que produzimos nesse post pode ser verificado e baixado aqui, nele possuí também classes de testes que não foram mostrados aqui mas foram criados para exemplificar.

Bônus

Com esse padrão também podemos encadear várias chamadas, para que vários processos possam ser executados de uma vez, para isso vamos imaginar que tenhamos um processo que ao recebermos um texto qualquer, devemos mandar um email para alguém, tenhamos que manipular esse texto, fazer um log e por fim enviar um SMS! Com o Design Pattern Command podemos encadear todas essas tarefas, para começarmos vamos definir a nossa interface Command:

Notem que dessa vez criamos apenas o “contrato” execute().

Nota: Dessa vez não vamos precisar da funcionalidade de desfazer.

Vamos agora criar as implementações para cada necessidade mencionada acima:

Podemos notar que cada um possuí uma implementação especifica, alguns possuí também construtores que precisamos informar algumas dados para que possam ser executados.

Agora vamos fazer tudo isso funcionar junto, para isso vamos criar a classe MainBonusCommand que vai orquestrar as chamadas:

Podemos notar que como ficou simples agora, e qualquer outra tarefa nova basta implementar a interface Command e colocarmos na lista que ele será executada, vamos executar essa classe principal com o comando:

ceb@cezb-note:designpattern-command$ cd ~/$WORKSPACE_HOME/java-designpatterns/designpattern-command-bonus
ceb@cezb-note:designpattern-command-bonus$ mvn exec:java -Dstart-class=br.com.batistao.MainBonusCommand

E teremos um output parecido com o mostrado abaixo:

...
[INFO] --- exec-maven-plugin:1.3.2:java (default-cli) @ designpattern-command-bonus ---
[WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
Enviando e-mail de: remetente@email.com.br, para: destinatario@email.com.br, com assunto: Command Queue, com o texto: Encadeando processos com o Design Pattern Command!
Manipulando o texto: Encadeando processos com o Design Pattern Command!
Escrevendo no log...
Enviando SMS para: (99) 99999-9999
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

...

Bem bacana né? Espero que tenham gostado!

Nota: Todo o código que produzimos nesse post pode ser verificado e baixado aqui.

3 comentários em “Design Pattern: Command

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s