0Pricing
PHP Academy · Lección

Patrones de comportamiento: Strategy, Observer y Command

Modele el comportamiento y la comunicación mediante patrones de comportamiento.

Patrones de comportamiento: Strategy, Observer y Command es una lección gratuita de PHP Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de PHP Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de PHP Academy incluye 4 lecciones en total.

Modelar el comportamiento

Los patrones de comportamiento regulan cómo colaboran los objetos y distribuyen las responsabilidades. Nos centraremos en tres que aparecen constantemente en sistemas PHP reales:

  • Strategy — permite cambiar un algoritmo durante la ejecución.
  • Observer — difunde eventos a los listeners interesados.
  • Command — convierte una solicitud en un objeto que puede ponerse en cola, registrarse o deshacerse.

Strategy: la idea

El patrón Strategy define una familia de algoritmos intercambiables detrás de una única interfaz y permite que el cliente elija uno durante la ejecución. Sustituye el extenso switch que aparece a continuación por polimorfismo: el contexto delega en la estrategia que contiene.

<?php
// The smell Strategy removes: branching on a type code
function price(string $type, float $base): float {
    switch ($type) {
        case 'standard': return $base + 5;
        case 'express':  return $base + 15;
        default: throw new InvalidArgumentException($type);
    }
}
echo price('express', 10), PHP_EOL; // 25

Strategy en código

Aquí, el coste de envío depende del transportista elegido. Cada estrategia encapsula un algoritmo de tarificación; el contexto no cambia cuando se añade un transportista.

<?php
interface ShippingStrategy { public function cost(float $weight): float; }
final class Standard implements ShippingStrategy {
    public function cost(float $w): float { return 5 + $w * 0.5; }
}
final class Express implements ShippingStrategy {
    public function cost(float $w): float { return 15 + $w * 1.2; }
}

final class Cart {
    public function __construct(private ShippingStrategy $strategy) {}
    public function setStrategy(ShippingStrategy $s): void { $this->strategy = $s; }
    public function quote(float $weight): float { return $this->strategy->cost($weight); }
}

$cart = new Cart(new Standard());
echo $cart->quote(10), PHP_EOL;     // 10
$cart->setStrategy(new Express());
echo $cart->quote(10), PHP_EOL;     // 27

Strategy con closures

En PHP, una estrategia no siempre necesita una clase. En casos sencillos, un callable o la sintaxis de callable de primera clase es una estrategia perfectamente válida. Utilice clases completas cuando el algoritmo tenga su propio estado o dependencias; utilice closures para decisiones sencillas y sin estado.

<?php
$strategies = [
    'asc'  => fn(array $a) => sort($a) ? $a : $a,
    'desc' => fn(array $a) => rsort($a) ? $a : $a,
];
$data = [3, 1, 2];
print_r($strategies['desc']($data)); // [3,2,1]

Observer: la idea

El patrón Observer permite que un sujeto notifique a muchos observadores cuando cambia su estado, sin saber quiénes son. Esto desacopla la fuente de un evento de sus gestores y sustenta los sistemas de eventos, los hooks y las actualizaciones reactivas.

Observer en código

El sujeto mantiene una lista de observadores y llama a update() en cada uno. Los nuevos listeners pueden conectarse sin cambiar la lógica del sujeto.

<?php
interface Observer { public function update(string $event): void; }

final class OrderSubject {
    private array $observers = [];
    public function subscribe(Observer $o): void { $this->observers[] = $o; }
    public function placed(string $id): void {
        foreach ($this->observers as $o) { $o->update("order $id placed"); }
    }
}
final class EmailObserver implements Observer {
    public function update(string $e): void { echo "email: $e" . PHP_EOL; }
}
final class AuditObserver implements Observer {
    public function update(string $e): void { echo "audit: $e" . PHP_EOL; }
}

$subject = new OrderSubject();
$subject->subscribe(new EmailObserver());
$subject->subscribe(new AuditObserver());
$subject->placed('42');

Observer frente a PSR-14

El PHP moderno suele expresar Observer mediante despachadores de eventos PSR-14: un despachador dirige un objeto de evento a los listeners registrados. El modelo mental es el mismo (sujeto = evento, observadores = listeners), pero un despachador los desacopla aún más y admite eventos que se pueden detener. SplObserver/SplSubject existen en la SPL, pero hoy se utilizan muy poco.

Command: la idea

El patrón Command encapsula una solicitud como un objeto: la acción, su receptor y sus parámetros. Como la solicitud pasa a ser datos, puede ponerse en cola, registrarse, reintentarse o deshacerse. El comando más sencillo simplemente convierte una intención en un valor, como se muestra a continuación.

<?php
final class SendEmail {
    public function __construct(
        public readonly string $to,
        public readonly string $subject
    ) {}
}
// The request is now data you can store, serialize, or enqueue
$cmd = new SendEmail('user@example.com', 'Welcome');
echo json_encode($cmd), PHP_EOL;

Command en código

Cada comando implementa execute(). Un invocador los almacena y ejecuta, desacoplado de lo que hacen. Añadir undo() lo convierte en una pila completa de deshacer.

<?php
interface Command { public function execute(): string; }

final class Light { public bool $on = false; }
final class TurnOn implements Command {
    public function __construct(private Light $light) {}
    public function execute(): string { $this->light->on = true; return 'light on'; }
}
final class TurnOff implements Command {
    public function __construct(private Light $light) {}
    public function execute(): string { $this->light->on = false; return 'light off'; }
}

final class Invoker {
    private array $queue = [];
    public function add(Command $c): void { $this->queue[] = $c; }
    public function run(): void {
        foreach ($this->queue as $c) { echo $c->execute(), PHP_EOL; }
    }
}

$light = new Light();
$inv = new Invoker();
$inv->add(new TurnOn($light));
$inv->add(new TurnOff($light));
$inv->run();

Buses de comandos

Los frameworks construyen un bus de comandos sobre este patrón: un DTO de comando se despacha a exactamente un handler. El middleware que rodea el bus puede añadir transacciones, validación y registro de forma uniforme. Como los comandos son objetos simples y serializables, el mismo handler puede ejecutarse de forma síncrona o enviarse a un worker de cola.

Elegir entre ellos

  • Strategy: una operación, muchos algoritmos intercambiables, elegidos por el cliente.
  • Observer: un evento, muchas reacciones independientes; la fuente no conoce los handlers.
  • Command: materializa una solicitud para poder ponerla en cola, registrarla, reintentarlo o deshacerla.

Se combinan bien: un handler de comandos puede elegir una estrategia y emitir eventos para los observadores.

Comprobación rápida

Asocie el requisito con el patrón.

Resumen

Ha modelado el comportamiento con tres patrones: Strategy para cambiar algoritmos durante la ejecución (clases o closures), Observer para difundir cambios de estado a listeners desacoplados (la base de los despachadores PSR-14) y Command para convertir solicitudes en objetos que puede poner en cola, registrar y deshacer (la base de los buses de comandos). En conjunto, mantienen flexibles las colaboraciones y claras las responsabilidades.

Preguntas frecuentes

¿La lección «Patrones de comportamiento: Strategy, Observer y Command» es gratis?

Sí — el texto completo de «Patrones de comportamiento: Strategy, Observer y Command» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de PHP Academy, actualiza a CoddyKit PRO. El curso de PHP Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Patrones de comportamiento: Strategy, Observer y Command»?

Modele el comportamiento y la comunicación mediante patrones de comportamiento. Practicas PHP Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar PHP Academy?

No se requiere experiencia previa. PHP Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «Patrones de comportamiento: Strategy, Observer y Command»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de PHP Academy?

Sí. Cada lección de PHP Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Principios SOLID en la práctica
  2. Patrones creacionales: Factory, Builder y Singleton
  3. Patrones estructurales: Adapter, Decorator y Facade
  4. Patrones de comportamiento: Strategy, Observer y Command
← Volver a PHP Academy