Padrão Command
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 70 de 87.
O padrão Command é um padrão comportamental de projeto que transforma uma solicitação em um objeto independente contendo todas as informações sobre a solicitação. Essa transformação permite passar solicitações como argumentos de métodos, adiar ou enfileirar a execução de uma solicitação e oferecer suporte a 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 (invocador) leva o papel (comando) até a cozinha, onde ele pode ser colocado em uma fila, priorizado ou até mesmo cancelado. O padrão desacopla o objeto que invoca a operação daquele que a executa.
O padrão tem quatro componentes principais: uma interface Command que declara o método execute, classes ConcreteCommand que implementam ações específicas, um Receiver que realiza o trabalho de fato e um Invoker que aciona 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 invocador não sabe qual ação será realizada. 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 de Comando é excelente quando você precisa enfileirar operações, implementar funcionalidades 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 criar um sistema inteligente de automação residencial usando o Padrão de Comando! Você criará um sistema no qual 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, 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 executa a ação do comando.Devices.java: Crie duas classes receptoras que representam dispositivos domésticos inteligentes:Television- possui métodospowerOn()que imprimeTV is now ON,powerOff()que imprimeTV is now OFFesetChannel(int channel)que imprimeTV channel set to [channel].Thermostat- possui métodossetTemperature(int temp)que imprimeThermostat set to [temp] degreeseturnOff()que imprimeThermostat turned OFF.Commands.java: Crie classes de comando concretas que encapsulem 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 solicitante) que tenha um métodosetCommand(Command cmd)para armazenar um comando epressButton()para executar o comando armazenado.Em seu método principal, você receberá duas entradas: um número de canal de TV (inteiro) e uma temperatura do termostato (inteiro).
Crie uma
Televisione umThermostat. Crie umRemoteControle demonstre o Padrão de Comando:- Defina um
TVOnCommande pressione o botão - Defina um
TVChannelCommandcom o canal informado e pressione o botão - Defina um
ThermostatSetCommandcom a temperatura informada e pressione o botão - Defina um
TVOffCommande pressione o botão
- Defina um
Você receberá duas entradas, nesta 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 executar sua ação, facilitando a adição de novos dispositivos e comandos sem alterar o solicitante!
Experimente você mesmo
import java.util.Scanner;
// TODO: Crie a classe RemoteControl (o invocador) com:
// - método setCommand(Command cmd) para armazenar um comando
// - método pressButton() para executar o comando armazenado
class RemoteControl {
// TODO: Implemente RemoteControl
}
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Leia as entradas
int channel = scanner.nextInt();
int temperature = scanner.nextInt();
// TODO: Crie uma Television e um Thermostat
// TODO: Crie um RemoteControl
// TODO: Demonstre o Command Pattern:
// 1. Defina um TVOnCommand e pressione o botão
// 2. Defina um TVChannelCommand com o canal de entrada e pressione o botão
// 3. Set a ThermostatSetCommand with the input temperature and press the button
// 4. Defina um TVOffCommand e pressione 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 IteratorPratique por conta própria: Compilador de Java online