Patrón Command
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 75 de 91.
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étodo, retrasar o poner en cola la ejecución de una solicitud y admitir operaciones que se pueden deshacer.
Piensa en un restaurante.
Cuando pides comida, el camarero escribe tu pedido en una nota (el comando), la lleva a la cocina y el chef la ejecuta. El camarero no necesita saber cocinar; simplemente entrega el comando.
Esto desacopla al solicitante del ejecutor.
Aquí tienes una implementación básica:
<?php
interface Command {
public function execute(): string;
}class Light {
public function on(): string { return "Light is ON"; }
public function off(): string { return "Light is OFF"; }
}class LightOnCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->on();
}
}class LightOffCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->off();
}
}
El invocador activa comandos sin saber qué hacen:
<?php
class RemoteControl {
public function press(Command $command): string {
return $command->execute();
}
}$light = new Light();
$remote = new RemoteControl();
echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));
Resultado:
Light is ON
Light is OFFEl patrón Command sobresale cuando necesitas poner operaciones en cola, implementar la funcionalidad de deshacer o registrar acciones. Cada comando es autónomo, lo que facilita la adición de nuevos comandos sin modificar el código existente.
Desafío
FácilVamos a construir un sistema de comandos para un editor de texto utilizando el Patrón Command. Los editores de texto a menudo necesitan soportar operaciones como escribir texto, borrar texto y deshacer acciones; cada operación se convierte en un objeto de comando autónomo que puede ejecutarse a través de una interfaz unificada.
Organizarás tu código en cuatro archivos:
Command.php— Define una interfazCommandcon un único métodoexecute(): string. Esto establece el contrato que todos los comandos del editor deben seguir.TextEditor.php— Crea una claseTextEditorque represente al receptor: el objeto que realmente realiza el trabajo. Tu editor debe:- Almacenar el contenido de texto actual (comienza con una cadena vacía)
- Tener un método
write(string $text): stringque añada texto al contenido y devuelva"Written: [text]" - Tener un método
clear(): stringque vacíe el contenido y devuelva"Content cleared" - Tener un método
getContent(): stringque devuelva el contenido actual
Commands.php— Incluye los archivos Command y TextEditor. Crea dos clases de comando que implementen la interfazCommand:WriteCommand— Recibe unTextEditory una cadena de texto en su constructor. Su métodoexecute()llama al métodowrite()del editor y devuelve el resultado.ClearCommand— Recibe unTextEditoren su constructor. Su métodoexecute()llama al métodoclear()del editor y devuelve el resultado.
main.php— Incluye el archivo Commands. Recibirás dos entradas: un tipo de comando ("write"o"clear") y una cadena de texto (utilizada solo para los comandos de escritura).Crea una instancia de
TextEditor. Basándote en el tipo de comando, crea el objeto de comando apropiado. Luego, crea una función invocadora o un mecanismo simple que llame aexecute()en el comando e imprima el resultado.En una nueva línea, imprime el contenido actual del editor en este formato:
Content: [content](si está vacío, simplemente imprimeContent:sin nada después del espacio).
Este desafío demuestra cómo el Patrón Command encapsula cada operación como un objeto. El invocador no necesita saber si está ejecutando un comando de escritura o de limpieza; simplemente llama a execute() y deja que el comando maneje los detalles.
Hoja de referencia
El Patrón Command es un patrón de diseño de comportamiento que encapsula una solicitud como un objeto independiente que contiene toda la información sobre la misma. Esto permite pasar solicitudes como argumentos de método, poner operaciones en cola y admitir acciones que se pueden deshacer.
El patrón desacopla al solicitante (invocador) del ejecutor (receptor), de manera similar a cómo un camarero entrega los pedidos a un chef sin necesidad de saber cocinar.
Estructura Básica
Define una interfaz Command con un método execute():
interface Command {
public function execute(): string;
}Crea una clase receptora que realice el trabajo real:
class Light {
public function on(): string { return "Light is ON"; }
public function off(): string { return "Light is OFF"; }
}Implementa clases de comando concretas que encapsulen acciones específicas:
class LightOnCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->on();
}
}
class LightOffCommand implements Command {
public function __construct(private Light $light) {}
public function execute(): string {
return $this->light->off();
}
}Invocador
El invocador activa los comandos sin conocer los detalles de su implementación:
class RemoteControl {
public function press(Command $command): string {
return $command->execute();
}
}
$light = new Light();
$remote = new RemoteControl();
echo $remote->press(new LightOnCommand($light)) . "\n";
echo $remote->press(new LightOffCommand($light));Beneficios
El Patrón Command es ideal para poner operaciones en cola, implementar la funcionalidad de deshacer o registrar acciones. Cada comando es autónomo, lo que facilita la adición de nuevos comandos sin modificar el código existente.
Pruébalo tú mismo
<?php
require_once 'Commands.php';
// Leer entrada
$commandType = trim(fgets(STDIN)); // "write" o "clear"
$text = trim(fgets(STDIN)); // texto para el comando write
// TODO: Crear una instancia de TextEditor
// TODO: Basado en el tipo de comando, crear el objeto de comando apropiado
// - Si es "write", crear un WriteCommand con el editor y el texto
// - Si es "clear", crear un ClearCommand con el editor
// TODO: Crear un mecanismo invocador que llame a execute() en el comando
// y que imprima el resultado
// TODO: Imprimir el contenido actual del editor en el formato: "Content: [content]"
// (si está vacío, simplemente imprimir "Content: " sin nada después del espacio)
?>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 OOPClases vs ObjetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Resumen - Calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasResumen - Jerarquía de empleados7Encapsulamiento
Público, Protegido, PrivadoModificadores de acceso a fondoGetters y SettersOcultamiento de informaciónPromoción de constructor (8.0)Resumen - Sistema de registros de estudiantes10Conceptos avanzados de POO
Composición vs. HerenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibers (PHP 8.1)Clonación de objetos a fondoGeneradores e Iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Espacios de nombres y Autoloading
Introducción a los espacios de nombresLa palabra clave useEstándar de Autoloading PSR-4Autoloader de ComposerResumen - Proyecto organizado5Interfaces y Contratos
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesInterfaz vs Clase AbstractaType Hinting con InterfacesResumen - Calculadora de Formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeResumen - Colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Resumen - Gestor de cuenta bancaria6Polimorfismo
Sobrescritura de métodos revisadaPolimorfismo mediante interfacesType Hinting y tipos de uniónEnlace estático tardíoResumen - Procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos de TraitsMétodos abstractos en TraitsTraits frente a herencia12Patrones de diseño Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón Strategy