Patrón Command
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy. Lección 70 de 87.
El patrón Command es un patrón de diseño de comportamiento que convierte una solicitud en un objeto independiente que contiene toda la información sobre la solicitud. Esta transformación te permite pasar solicitudes como argumentos de métodos, retrasar o poner en cola la ejecución de una solicitud y admitir operaciones que se pueden deshacer.
Piensa en ello como en un restaurante: en lugar de decirle directamente al chef qué cocinar, escribes tu pedido en una comanda. El camarero (invocador) lleva la comanda (comando) a la cocina, donde puede ponerse en cola, priorizarse o incluso cancelarse. El patrón desacopla el objeto que invoca la operación del que la ejecuta.
El patrón tiene cuatro componentes clave: una interfaz Command que declara el método execute, clases ConcreteCommand que implementan acciones específicas, un Receiver que realiza el trabajo real y un Invoker que activa los 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();
}
}El invocador no sabe qué acción se realizará. Simplemente llama a execute():
Light light = new Light();
Command lightOn = new LightOnCommand(light);
RemoteControl remote = new RemoteControl();
remote.setCommand(lightOn);
remote.pressButton(); // Salida: Light is ONEl patrón Command es excelente cuando necesitas poner operaciones en cola, implementar la funcionalidad de deshacer/rehacer o programar tareas para ejecutarlas más adelante. Cada comando encapsula todo lo necesario para realizar una acción, lo que hace que tu sistema sea más flexible y extensible.
Desafío
Fácil¡Construyamos un sistema de automatización inteligente del hogar usando el patrón Command! Crearás un sistema en el que varios dispositivos del hogar se pueden controlar mediante comandos, lo que permite poner acciones en cola, ejecutarlas e incluso almacenarlas para usarlas más adelante, como un control remoto universal que no necesita saber cómo funciona internamente cada dispositivo.
Organizarás tu código en cuatro archivos:
Command.java: Define la interfazCommandque implementarán todos los comandos de los dispositivos. Debe declarar un único métodoexecute()que realice la acción del comando.Devices.java: Crea dos clases receptoras que representen dispositivos inteligentes del hogar:Television: tiene métodospowerOn()que imprimeTV is now ON,powerOff()que imprimeTV is now OFFysetChannel(int channel)que imprimeTV channel set to [channel].Thermostat: tiene métodossetTemperature(int temp)que imprimeThermostat set to [temp] degreesyturnOff()que imprimeThermostat turned OFF.Commands.java: Crea clases de comandos concretos que encapsulen las operaciones de los dispositivos:TVOnCommand: recibe unTelevisionen su constructor y llama apowerOn()cuando se ejecuta.TVOffCommand: recibe unTelevisionen su constructor y llama apowerOff()cuando se ejecuta.TVChannelCommand: recibe unTelevisiony unint channelen su constructor, y llama asetChannel()con ese canal cuando se ejecuta.ThermostatSetCommand: recibe unThermostaty unint temperatureen su constructor, y llama asetTemperature()con ese valor cuando se ejecuta.Main.java: Crea una claseRemoteControl(el invocador) que tenga un métodosetCommand(Command cmd)para almacenar un comando ypressButton()para ejecutar el comando almacenado.En tu método main, recibirás dos entradas: un número de canal de TV (entero) y una temperatura del termostato (entero).
Crea un
Televisiony unThermostat. Crea unRemoteControly demuestra el patrón Command de la siguiente manera:- Establece un
TVOnCommandy presiona el botón - Establece un
TVChannelCommandcon el canal introducido y presiona el botón - Establece un
ThermostatSetCommandcon la temperatura introducida y presiona el botón - Establece un
TVOffCommandy presiona el botón
- Establece un
Recibirás dos entradas en orden: el canal de TV (entero) y la temperatura del termostato (entero).
Por ejemplo, con las entradas 5 y 72, tu salida sería:
TV is now ON
TV channel set to 5
Thermostat set to 72 degrees
TV is now OFFObserva que RemoteControl nunca interactúa directamente con los dispositivos. Solo conoce la interfaz Command. Cada comando encapsula todo lo necesario para realizar su acción, lo que facilita agregar nuevos dispositivos y comandos sin cambiar el invocador.
Pruébalo tú mismo
import java.util.Scanner;
// TODO: Crea la clase RemoteControl (el invocador) con:
// - método setCommand(Command cmd) para almacenar un comando
// - método pressButton() para ejecutar el comando almacenado
class RemoteControl {
// TODO: Implementa RemoteControl
}
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lee las entradas
int channel = scanner.nextInt();
int temperature = scanner.nextInt();
// TODO: Crea un Television y un Thermostat
// TODO: Crea un RemoteControl
// TODO: Demuestra el patrón Command:
// 1. Establece un TVOnCommand y presiona el botón
// 2. Establece un TVChannelCommand con el canal de entrada y presiona el botón
// 3. Set a ThermostatSetCommand with the input temperature and press the button
// 4. Establece un TVOffCommand y presiona el botón
scanner.close();
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón IteratorPractica por tu cuenta: Compilador de Java online