O padrão Command é um padrão de design comportamental que tem como objetivo principal encapsular uma solicitação como um objeto, permitindo assim parametrizar clientes com diferentes solicitações, enfileirar ou registrar operações e implementar operações reversíveis. Este padrão é usado para resolver vários problemas:
-
Separação entre Solicitações e Executores: O Command separa o objeto que emite uma solicitação do objeto que sabe como executá-la. Isso permite que solicitações sejam tratadas como objetos independentes que podem ser passados e armazenados por outros objetos.
-
Flexibilidade e Reutilização de Solicitações: Comandos encapsulados como objetos podem ser reutilizados em diferentes contextos e situações, aumentando a flexibilidade e a possibilidade de reutilização de código.
-
Gerenciamento e Extensão de Operações: O padrão Command permite operações como enfileiramento, registro (logging), e desfazimento (undo) de comandos. Isso é útil em aplicações complexas, onde tais operações são necessárias.
-
Parametrização de Objetos com Operações: Objetos podem ser parametrizados com diferentes comandos, permitindo que a mesma operação seja realizada de maneiras diferentes, dependendo do comando específico fornecido.
-
Desacoplamento de Tempo: Os comandos permitem que as solicitações sejam enfileiradas e executadas em momentos diferentes, não necessariamente no instante em que foram emitidas.
Como Funciona
O padrão Command envolve os seguintes componentes:
- Command (Interface ou Classe Abstrata): Define uma interface para a execução de uma operação.
- ConcreteCommand: Implementa a interface Command e encapsula a lógica da operação. Ele mantém uma referência ao objeto receptor, que executa a operação.
- Invoker: É responsável por acionar o comando. Não sabe nada sobre a operação específica que está sendo realizada.
- Receiver: Conhece como realizar a operação. O objeto que possui a lógica de negócio.
- Client: Cria e configura os objetos ConcreteCommand com seus respectivos Receivers.
Exemplo
Um exemplo clássico do uso do padrão Command é em interfaces gráficas de usuário (GUIs), onde ações do usuário (como cliques em botões) são mapeadas para comandos específicos que realizam operações. Outro exemplo é em sistemas de automação, onde diferentes comandos podem ser enfileirados e executados sequencialmente para automatizar uma série de ações.
Exemplo de Implementação
Vamos criar um exemplo simples do padrão Command em Java. Vamos desenvolver um sistema básico de controle remoto que pode executar duas ações: ligar e desligar um dispositivo (por exemplo, uma TV).
Interface Command
Primeiro, definimos a interface Command, que será implementada por todos os comandos:
public interface Command {
void execute();
}Comandos Concretos
Implementamos comandos concretos para ligar e desligar a TV:
public class TurnOnCommand implements Command {
private TV tv;
public TurnOnCommand(TV tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.turnOn();
}
}
public class TurnOffCommand implements Command {
private TV tv;
public TurnOffCommand(TV tv) {
this.tv = tv;
}
@Override
public void execute() {
tv.turnOff();
}
}Classe Receiver
A classe TV representa o dispositivo que será controlado pelos comandos:
public class TV {
public void turnOn() {
System.out.println("TV está ligada.");
}
public void turnOff() {
System.out.println("TV está desligada.");
}
}Invoker
A classe RemoteControl atua como um invocador que pode executar comandos:
public class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}Testando o Padrão Command
Por fim, usamos o padrão Command para controlar a TV:
public class Main {
public static void main(String[] args) {
TV tv = new TV();
Command turnOn = new TurnOnCommand(tv);
Command turnOff = new TurnOffCommand(tv);
RemoteControl remote = new RemoteControl();
remote.setCommand(turnOn);
remote.pressButton();
remote.setCommand(turnOff);
remote.pressButton();
}
}Neste exemplo, a classe RemoteControl é configurada com diferentes comandos (TurnOnCommand e TurnOffCommand) para controlar a TV. Isso demonstra como o padrão Command permite a separação entre o objeto que emite o comando (o controle remoto) e o objeto que realiza a operação (a TV), além de possibilitar a troca dinâmica dos comandos executados.