Menu
Coddy logo textTech

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 ON

O 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.

challenge icon

Desafio

Fácil

Vamos 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 interface Command que todos os comandos de dispositivos implementarão. Ela deve declarar um único método execute() que realiza a ação do comando.
  • Devices.java: Crie duas classes receptoras que representam dispositivos domésticos inteligentes:

    Television - possui os métodos powerOn() que imprime "TV is now ON", powerOff() que imprime "TV is now OFF", e setChannel(int channel) que imprime "TV channel set to " + channel.

    Thermostat - possui os métodos setTemperature(int temp) que imprime "Thermostat set to " + temp + " degrees" e turnOff() que imprime "Thermostat turned OFF".

  • Commands.java: Crie classes de comando concretas que encapsulam as operações dos dispositivos:

    TVOnCommand - recebe uma Television em seu construtor e chama powerOn() quando executado.

    TVOffCommand - recebe uma Television em seu construtor e chama powerOff() quando executado.

    TVChannelCommand - recebe uma Television e um int channel em seu construtor, e chama setChannel() com esse canal quando executado.

    ThermostatSetCommand - recebe um Thermostat e um int temperature em seu construtor, e chama setTemperature() com esse valor quando executado.

  • Main.java: Crie uma classe RemoteControl (o invoker) que possui um método setCommand(Command cmd) para armazenar um comando e pressButton() 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 Television e um Thermostat. Crie um RemoteControl e demonstre o Command Pattern ao:

    1. Configurar um TVOnCommand e pressionar o botão
    2. Configurar um TVChannelCommand com o seu canal de entrada e pressionar o botão
    3. Configurar um ThermostatSetCommand com a sua temperatura de entrada e pressionar o botão
    4. Configurar um TVOffCommand e pressionar o botão

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 OFF

Observe 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 ON

O 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();
    }
}
quiz iconTeste seus conhecimentos

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