Padrão Command
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 70 de 87.
O Command Pattern é um padrão de projeto comportamental que transforma uma solicitação em um objeto independente que contém todas as informações sobre a solicitação. Essa transformação permite que você passe solicitações como argumentos de método, atrase ou coloque a execução de uma solicitação em fila e suporte operações que podem ser desfeitas.
Pense nisso como um restaurante: em vez de dizer diretamente ao chef o que cozinhar, você escreve seu pedido em um papel. O garçom (invoker) leva o papel (command) para a cozinha, onde ele pode ser enfileirado, priorizado ou até cancelado. O padrão desacopla o objeto que invoca a operação daquele que a executa.
O padrão possui quatro componentes principais: uma interface Command declarando o método execute, classes ConcreteCommand que implementam ações específicas, um Receiver que realiza o trabalho real e um Invoker que dispara os comandos:
interface Command {
void execute();
}class Light { // Receptor
public void turnOn() {
System.out.println("Light is ON");
}
public void turnOff() {
System.out.println("Light is OFF");
}
}class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}class RemoteControl { // Invocador
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}O invoker não sabe qual ação será executada — ele apenas chama execute():
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // Saída: Light is ONO Padrão Command se destaca quando você precisa enfileirar operações, implementar a funcionalidade de desfazer/refazer ou agendar tarefas para execução posterior. Cada comando encapsula tudo o que é necessário para realizar uma ação, tornando seu sistema mais flexível e extensível.
Desafio
FácilVamos construir um sistema de automação residencial inteligente usando o Command Pattern! Você criará um sistema onde vários dispositivos domésticos podem ser controlados por meio de comandos, permitindo que as ações sejam enfileiradas, executadas e até armazenadas para uso posterior — exatamente como um controle remoto universal que não precisa saber como cada dispositivo funciona internamente.
Você organizará seu código em quatro arquivos:
Command.java: Defina a interfaceCommandque todos os comandos de dispositivos implementarão. Ela deve declarar um único métodoexecute()que realiza a ação do comando.Devices.java: Crie duas classes receptoras que representam dispositivos domésticos inteligentes:Television- possui os métodospowerOn()que imprime"TV is now ON",powerOff()que imprime"TV is now OFF", esetChannel(int channel)que imprime"TV channel set to " + channel.Thermostat- possui os métodossetTemperature(int temp)que imprime"Thermostat set to " + temp + " degrees"eturnOff()que imprime"Thermostat turned OFF".Commands.java: Crie classes de comando concretas que encapsulam as operações dos dispositivos:TVOnCommand- recebe umaTelevisionem seu construtor e chamapowerOn()quando executado.TVOffCommand- recebe umaTelevisionem seu construtor e chamapowerOff()quando executado.TVChannelCommand- recebe umaTelevisione umint channelem seu construtor, e chamasetChannel()com esse canal quando executado.ThermostatSetCommand- recebe umThermostate umint temperatureem seu construtor, e chamasetTemperature()com esse valor quando executado.Main.java: Crie uma classeRemoteControl(o invoker) que possui um métodosetCommand(Command cmd)para armazenar um comando epressButton()para executar o comando armazenado.No seu método main, você receberá duas entradas: um número de canal de TV (inteiro) e uma temperatura de termostato (inteiro).
Crie uma
Televisione umThermostat. Crie umRemoteControle demonstre o Command Pattern ao:- Configurar um
TVOnCommande pressionar o botão - Configurar um
TVChannelCommandcom o seu canal de entrada e pressionar o botão - Configurar um
ThermostatSetCommandcom a sua temperatura de entrada e pressionar o botão - Configurar um
TVOffCommande pressionar o botão
- Configurar um
Você receberá duas entradas em ordem: o canal da TV (inteiro) e a temperatura do termostato (inteiro).
Por exemplo, com as entradas 5 e 72, sua saída seria:
TV is now ON
TV channel set to 5
Thermostat set to 72 degrees
TV is now OFFObserve como o RemoteControl nunca interage diretamente com os dispositivos — ele conhece apenas a interface Command. Cada comando encapsula tudo o que é necessário para realizar sua ação, facilitando a adição de novos dispositivos e comandos sem alterar o invoker!
Folha de consulta
O Command Pattern (Padrão de Comando) é um padrão de design comportamental que encapsula uma solicitação como um objeto, permitindo que você parametrize clientes com diferentes solicitações, enfileire ou registre solicitações e suporte operações que podem ser desfeitas.
O padrão desacopla o objeto que invoca a operação (invoker) daquele que a executa (receiver).
Componentes Principais
- Command: Interface que declara o método
execute() - ConcreteCommand: Classes que implementam ações específicas
- Receiver: Objeto que realiza o trabalho real
- Invoker: Objeto que aciona os comandos
Estrutura Básica
// Interface Command
interface Command {
void execute();
}
// Receiver
class Light {
public void turnOn() {
System.out.println("Light is ON");
}
public void turnOff() {
System.out.println("Light is OFF");
}
}
// ConcreteCommand
class LightOnCommand implements Command {
private Light light;
public LightOnCommand(Light light) {
this.light = light;
}
public void execute() {
light.turnOn();
}
}
// Invoker
class RemoteControl {
private Command command;
public void setCommand(Command command) {
this.command = command;
}
public void pressButton() {
command.execute();
}
}Uso
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // Saída: Light is ONO invoker não sabe qual ação será executada — ele apenas chama execute(). Isso torna o sistema flexível e extensível, ideal para enfileirar operações, implementar a funcionalidade de desfazer/refazer ou agendar tarefas.
Experimente você mesmo
import java.util.Scanner;
// TODO: Criar a classe RemoteControl (o invoker) com:
// - método setCommand(Command cmd) para armazenar um comando
// - método pressButton() para executar o comando armazenado
class RemoteControl {
// TODO: Implementar RemoteControl
}
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler as entradas
int channel = scanner.nextInt();
int temperature = scanner.nextInt();
// TODO: Criar uma Television e um Thermostat
// TODO: Criar um RemoteControl
// TODO: Demonstrar o Command Pattern:
// 1. Configurar um TVOnCommand e pressionar o botão
// 2. Configurar um TVChannelCommand com o canal de entrada e pressionar o botão
// 3. Configurar um ThermostatSetCommand com a temperatura de entrada e pressionar o botão
// 4. Configurar um TVOffCommand e pressionar o botão
scanner.close();
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator