0Pricing
PHP Academy · Lección

Patrones creacionales: Factory, Builder y Singleton

Controle la creación de objetos de forma clara mediante patrones creacionales.

Patrones creacionales: Factory, Builder y Singleton es una lección gratuita de PHP Academy en CoddyKit. Esta es la lección 2 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.

Controlar la creación

Los patrones creacionales desacoplan lo que necesita de cómo se construye. Cuando la construcción es condicional, consta de varios pasos o debe centralizarse, distribuir new por el código acopla a los clientes a clases concretas. Aquí cubrimos Factory (y Factory Method), Builder para ensamblajes complejos y Singleton (con sus consideraciones).

Simple Factory

Una simple factory centraliza una decisión de creación detrás de un único método. Los clientes solicitan un tipo lógico y reciben una instancia concreta configurada, sin conocer los nombres de las clases.

<?php
interface Notifier { public function send(string $msg): string; }
final class EmailNotifier implements Notifier {
    public function send(string $m): string { return "email: $m"; }
}
final class SmsNotifier implements Notifier {
    public function send(string $m): string { return "sms: $m"; }
}

final class NotifierFactory {
    public static function make(string $channel): Notifier {
        return match ($channel) {
            'email' => new EmailNotifier(),
            'sms'   => new SmsNotifier(),
            default => throw new InvalidArgumentException($channel),
        };
    }
}
echo NotifierFactory::make('sms')->send('Hi'), PHP_EOL;

Factory Method

El patrón Factory Method delega la instanciación en las subclases. La clase base define un algoritmo que llama a un create() abstracto; cada subclase decide cuál es el producto concreto. Es compatible con OCP: permite añadir un creador sin modificar los existentes.

<?php
abstract class ReportExporter {
    abstract protected function create(): string;
    public function export(): string {
        return 'Exported as ' . $this->create();
    }
}
final class PdfExporter extends ReportExporter {
    protected function create(): string { return 'PDF'; }
}
final class CsvExporter extends ReportExporter {
    protected function create(): string { return 'CSV'; }
}
echo (new PdfExporter())->export(), PHP_EOL;
echo (new CsvExporter())->export(), PHP_EOL;

Abstract Factory

Una Abstract Factory produce familias de objetos relacionados que deben utilizarse conjuntamente (p. ej., un MySqlConnection y un MySqlQueryBuilder). Garantiza que las partes sean compatibles porque una única fábrica proporciona el conjunto completo. Utilícela cuando una familia de productos deba mantener la coherencia interna.

Builder: el problema

Cuando un objeto necesita muchos parámetros opcionales, los constructores terminan convertidos en listas ilegibles de argumentos posicionales o en sobrecargas telescópicas, que PHP ni siquiera admite. El patrón Builder ensambla un objeto complejo paso a paso y devuelve al final un producto terminado y válido.

Builder fluido

Un builder fluido devuelve $this desde cada setter y, después, build() produce el resultado inmutable. Así, el producto se mantiene sencillo y la lógica de ensamblaje se traslada al builder.

<?php
final class Query {
    public function __construct(public readonly string $sql) {}
}
final class QueryBuilder {
    private string $table = '';
    private array $where = [];
    public function from(string $t): self { $this->table = $t; return $this; }
    public function where(string $c): self { $this->where[] = $c; return $this; }
    public function build(): Query {
        $sql = "SELECT * FROM {$this->table}";
        if ($this->where) { $sql .= ' WHERE ' . implode(' AND ', $this->where); }
        return new Query($sql);
    }
}
echo (new QueryBuilder())->from('users')->where('age > 18')->build()->sql, PHP_EOL;

Builder frente a constructores con nombre

En casos más sencillos, los argumentos con nombre de PHP 8 y los constructores con nombre (métodos de fábrica estáticos) suelen ser preferibles a un builder completo.

  • Utilice argumentos con nombre cuando todos los datos estén disponibles de una vez.
  • Utilice un builder cuando el ensamblaje conste de varios pasos, sea condicional o se reutilice desde varios puntos de llamada.
<?php
final class Money {
    private function __construct(public readonly int $cents, public readonly string $cur) {}
    public static function fromDollars(float $d): self {
        return new self((int) round($d * 100), 'USD');
    }
    public static function zero(string $cur = 'USD'): self {
        return new self(0, $cur);
    }
}
var_dump(Money::fromDollars(19.99)->cents); // int(1999)

Singleton

Un Singleton garantiza una única instancia mediante un punto de acceso global. Impleméntelo con un constructor privado y un accesor estático. Es realmente útil para aquello que deba ser único dentro de un proceso, pero también es el patrón del que más se abusa.

<?php
final class Config {
    private static ?self $instance = null;
    private array $data = ['debug' => true];
    private function __construct() {}
    public static function instance(): self {
        return self::$instance ??= new self();
    }
    public function get(string $k): mixed { return $this->data[$k] ?? null; }
}
var_dump(Config::instance()->get('debug'));
var_dump(Config::instance() === Config::instance()); // true

Por qué Singleton causa problemas

Los Singleton introducen estado global oculto: los clientes acceden a Config::instance() en lugar de declarar la dependencia, lo que perjudica la capacidad de prueba y el paralelismo. En el PHP moderno, prefiera registrar una única instancia compartida en un contenedor de DI (ciclo de vida de «instancia única») e inyectarla. Obtendrá una sola instancia sin el acoplamiento global.

Elegir la herramienta adecuada

  • Simple/Factory Method: ocultan las clases concretas detrás de una decisión de creación.
  • Abstract Factory: produce familias de productos compatibles.
  • Builder: ensambla objetos complejos paso a paso.
  • Singleton: último recurso; prefiera servicios compartidos gestionados por el contenedor.

Los cuatro reducen el acoplamiento con los constructores concretos, lo que facilita ampliar y probar el código.

Factory basada en un registro

Una factory más dinámica busca los creadores en un registro, de modo que los tipos nuevos se registren por sí mismos sin modificar la factory (cumplimiento real de OCP). Así es como los sistemas de plugins y los serializadores resuelven un nombre de tipo y lo convierten en un constructor durante la ejecución.

<?php
interface Shape { public function name(): string; }
final class Circle implements Shape { public function name(): string { return 'circle'; } }
final class Square implements Shape { public function name(): string { return 'square'; } }

final class ShapeRegistry {
    private array $creators = [];
    public function register(string $key, callable $factory): void {
        $this->creators[$key] = $factory;
    }
    public function create(string $key): Shape {
        return ($this->creators[$key] ?? throw new InvalidArgumentException($key))();
    }
}
$r = new ShapeRegistry();
$r->register('circle', fn() => new Circle());
$r->register('square', fn() => new Square());
echo $r->create('square')->name(), PHP_EOL; // square

Comprobación rápida

Elija la herramienta creacional más adecuada para el escenario.

Resumen

Ha controlado la creación de objetos mediante patrones creacionales: factories para ocultar tipos concretos y elegir familias de productos, builders para ensamblar objetos complejos de forma fluida y Singleton, con sus ventajas y desventajas. La conclusión moderna es la siguiente: utilice factories y builders sin reparos, pero sustituya Singleton por el ciclo de vida de instancia compartida de un contenedor de DI para mantener las dependencias explícitas y comprobables.

Preguntas frecuentes

¿La lección «Patrones creacionales: Factory, Builder y Singleton» es gratis?

Sí — el texto completo de «Patrones creacionales: Factory, Builder y Singleton» 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 creacionales: Factory, Builder y Singleton»?

Controle la creación de objetos de forma clara mediante patrones creacionales. 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 2 de 4.

¿Cuánto tiempo toma la lección «Patrones creacionales: Factory, Builder y Singleton»?

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