
O Padrão de Projetos Command, também conhecido como “Comando” em português, é um padrão comportamental que encapsula uma solicitação como um objeto.
Essa abordagem permite que você parametrize clientes com diferentes solicitações, enfileire ou registre solicitações e implemente recursos de desfazer e refazer ações.
Em termos simples, o Command atua como um intermediário entre o cliente que deseja realizar uma ação e o objeto que sabe como executá-la.
Isso promove maior flexibilidade, desacoplamento e reuso de código. O uso desse padrão é amplamente aplicável em diversas situações onde comandos precisam ser executados, armazenados ou revertidos.
Sumário do Artigo
1. Estrutura do Padrão Command
A estrutura do padrão de projetos Command consiste na criação de uma Interface Command, que será comum a todos os métodos, e na implementação de Classes Concretas de Comando, onde serão definidas as ações do programa, como, por exemplo, operações CRUD (Create, Read, Update, Delete).
Para facilitar o entendimento, vamos detalhar esses três elementos principais:
- Interface Command: Define a interface comum para todos os comandos. Essa interface normalmente contém um método
execute()
que invoca a ação específica do comando. - Classes Concretas de Comando: Implementam a interface Command e definem a lógica específica de cada ação. Cada comando encapsula uma solicitação e sabe como executá-la.
- Invoker (Invocador): É responsável por receber o comando, invocar o método
execute()
e gerenciar os comandos, como armazená-los em um histórico ou enfileirá-los para execução posterior.
Confira também:
2. Benefícios do Padrão de Projetos Command
Se você já está imerso no mundo dos sistemas, deve saber que os padrões de projeto são essenciais para a construção de sistemas bem estruturados e manuteníveis.
Resumidamente, os padrões de projeto, também conhecidos como design patterns, resolvem problemas comuns da engenharia de software, padronizando formas de resolver determinados problemas com regras bem definidas, o que proporciona inúmeros benefícios.
Aqui no site, temos conteúdos sobre padrões de projeto como Builder, Decorator e outros. Enfim, vamos entender os benefícios que o padrão de projeto da vez, Command, nos oferece.
2.1. Flexibilidade
Permite parametrizar clientes com diferentes solicitações, facilitando a adição de novos comandos sem afetar o código existente.
Por exemplo, em um aplicativo de edição de texto, novos comandos como “salvar”, “abrir” ou “imprimir” podem ser adicionados facilmente.
2.2. Desacoplamento
Separa o cliente do receptor da solicitação, promovendo maior modularidade e reuso de código.
Isso significa que o cliente não precisa saber detalhes sobre como o comando é executado, apenas que ele será executado.
2.3. Histórico e Desfazer/Refazer
Facilita a implementação de funcionalidades de histórico de ações e desfazer/refazer, pois os comandos podem ser armazenados e reutilizados.
Em aplicações complexas, como editores gráficos ou de texto, essa funcionalidade é essencial para melhorar a experiência do usuário.
2.4. Enfileiramento de Tarefas
Permite enfileirar comandos para execução posterior em uma ordem específica, útil para automatizar sequências de ações.
Isso é especialmente útil em sistemas de automação industrial ou processamento de lote.

3. Padrão de Projetos Command: Implementando Controle Remoto de TV
Para ilustrar o padrão de projetos Command em Java, vamos usar o seguinte cenário: construir uma estrutura para um controle remoto de uma TV.
Mais especificamente, vamos criar as ações de alguns dos principais botões de um controle remoto de TV.
Por exemplo, ligar, desligar, aumentar volume e diminuir volume. Cada botão do controle remoto pode ser representado por um comando concreto. Vamos entender como isso funciona:
3.1. Interface Command
Primeiramente, definimos a interface Command:
// Interface Command
interface ControleRemotoCommand {
void execute();
}
3.2. Comandos Concretos
Em seguida, implementamos as classes concretas de comando para diferentes ações, como aumentar o volume, diminuir o volume, ligar e desligar a TV:
// Comando concreto para aumentar o volume
class AumentarVolumeCommand implements ControleRemotoCommand {
private Televisao televisao;
public AumentarVolumeCommand(Televisao televisao) {
this.televisao = televisao;
}
@Override
public void execute() {
televisao.aumentarVolume();
}
}
// Comando concreto para diminuir o volume
class DiminuirVolumeCommand implements ControleRemotoCommand {
private Televisao televisao;
public DiminuirVolumeCommand(Televisao televisao) {
this.televisao = televisao;
}
@Override
public void execute() {
televisao.diminuirVolume();
}
}
// Comando concreto para ligar a TV
class LigarTVCommand implements ControleRemotoCommand {
private Televisao televisao;
public LigarTVCommand(Televisao televisao) {
this.televisao = televisao;
}
@Override
public void execute() {
televisao.ligar();
}
}
// Comando concreto para desligar a TV
class DesligarTVCommand implements ControleRemotoCommand {
private Televisao televisao;
public DesligarTVCommand(Televisao televisao) {
this.televisao = televisao;
}
@Override
public void execute() {
televisao.desligar();
}
}
3.3. Classe Receptora
A classe Televisao
representa o receptor das ações. Ou seja, os métodos de execução estarão nela. Por exemplo, o método ligar
define a TV como ligada (true). Vamos ver essa classe de perto para entender melhor:
class Televisao {
private boolean ligado;
private int volume;
public void ligar() {
ligado = true;
System.out.println("TV ligada.");
}
public void desligar() {
ligado = false;
System.out.println("TV desligada.");
}
public void aumentarVolume() {
if (ligado) {
volume++;
System.out.println("Volume aumentado para " + volume);
} else {
System.out.println("Não é possível aumentar o volume. A TV está desligada.");
}
}
public void diminuirVolume() {
if (ligado) {
volume--;
System.out.println("Volume diminuído para " + volume);
} else {
System.out.println("Não é possível diminuir o volume. A TV está desligada.");
}
}
}
3.4. Invoker (Invocador)
O invocador representa o controle remoto que recebe os comandos do usuário e os executa:
import java.util.ArrayList;
import java.util.List;
class ControleRemoto {
private List<ControleRemotoCommand> comandos;
public ControleRemoto() {
comandos = new ArrayList<>();
}
public void adicionarComando(ControleRemotoCommand comando) {
comandos.add(comando);
}
public void executarComandos() {
for (ControleRemotoCommand comando : comandos) {
comando.execute();
}
}
}
3.5. Uso do Padrão de Projetos Command
Vamos agora integrar todas essas partes para demonstrar o uso do padrão de projetos Command.
Já passamos por todas as etapas deste padrão: criamos a interface, os comandos concretos e a classe receptora.
Agora, vamos implementar o padrão em um método principal em Java:
public class Main {
public static void main(String[] args) {
Televisao tv = new Televisao();
ControleRemotoCommand ligarTV = new LigarTVCommand(tv);
ControleRemotoCommand desligarTV = new DesligarTVCommand(tv);
ControleRemotoCommand aumentarVolume = new AumentarVolumeCommand(tv);
ControleRemotoCommand diminuirVolume = new DiminuirVolumeCommand(tv);
ControleRemoto controle = new ControleRemoto();
controle.adicionarComando(ligarTV);
controle.adicionarComando(aumentarVolume);
controle.adicionarComando(diminuirVolume);
controle.adicionarComando(desligarTV);
controle.executarComandos();
}
}
Neste exemplo, o Main
cria instâncias dos comandos concretos e as associa ao controle remoto.
O controle remoto então executa cada comando na ordem em que foram adicionados, demonstrando como o padrão de projetos Command pode ser usado para organizar e modularizar a execução de ações.
Conclusão
O padrão de projetos Command é uma poderosa ferramenta para desenvolver software modular e flexível.
Ele permite que ações sejam encapsuladas como objetos, facilitando a adição de novos comandos e a implementação de funcionalidades como desfazer/refazer e enfileiramento de tarefas.
No exemplo do controle remoto de TV, vimos como implementar o padrão Command em Java, criando uma solução que desacopla o cliente do receptor das ações.
Esse padrão é amplamente aplicável em diversas áreas da programação, desde a automação de tarefas até o desenvolvimento de interfaces de usuário complexas.
Explorar e aplicar o padrão Command pode levar a um código mais limpo, reutilizável e fácil de manter, beneficiando tanto desenvolvedores quanto usuários finais.