Menu
Coddy logo textTech

Patrón Singleton

Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy — lección 71 de 91.

El Patrón Singleton es un patrón de diseño creacional que garantiza que una clase tenga una única instancia a lo largo del ciclo de vida de su aplicación. También proporciona un punto de acceso global a esa instancia.

Este patrón es útil cuando necesitas exactamente un objeto para coordinar acciones en todo el sistema, como una conexión a la base de datos, un gestor de configuración o un registrador (logger). Crear múltiples instancias de estos desperdiciaría recursos o causaría un comportamiento inconsistente.

Aquí tienes cómo implementar un Singleton en PHP:

<?php
class Database {
    private static ?Database $instance = null;
    
    private function __construct() {
        // El constructor privado evita la instanciación directa
    }
    
    public static function getInstance(): Database {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function query(string $sql): string {
        return "Executing: $sql";
    }
}

$db1 = Database::getInstance();
$db2 = Database::getInstance();

echo $db1 === $db2 ? "Same instance" : "Different instances";

Resultado:

Same instance

El patrón se basa en tres elementos clave: un constructor privado que impide el uso de new directamente, una propiedad estática que mantiene la instancia única y un método estático que crea la instancia en la primera llamada y la devuelve en las llamadas posteriores.

Para que el Singleton sea verdaderamente a prueba de balas, también debes evitar la clonación y la deserialización:

<?php
private function __clone() {}
public function __wakeup() {
    throw new Exception("Cannot unserialize singleton");
}
challenge icon

Desafío

Fácil

Vamos a construir un gestor de configuración utilizando el Patrón Singleton. En aplicaciones reales, normalmente se desea una única fuente de verdad para los ajustes de configuración; tener múltiples objetos de configuración podría provocar un comportamiento inconsistente en todo el sistema.

Organizarás tu código en dos archivos:

  • Config.php — Crea una clase Config que implemente el Patrón Singleton. Tu gestor de configuración debe:
    • Almacenar los ajustes en una propiedad de array privada
    • Tener un constructor privado que inicialice el array de ajustes como vacío
    • Proporcionar un método estático getInstance() que devuelva la instancia única
    • Evitar la clonación haciendo que __clone() sea privado
    • Incluir un método set(string $key, string $value): void para almacenar un ajuste
    • Incluir un método get(string $key): ?string que devuelva el valor de una clave, o null si la clave no existe
    • Incluir un método getAll(): array que devuelva todos los ajustes
  • main.php — Incluye el archivo Config. Recibirás dos entradas: una clave y un valor.

    Obtén la instancia de Config y establece un ajuste predeterminado con la clave "app_name" y el valor "MyApp".

    Obtén una segunda referencia a la instancia de Config (usando getInstance() de nuevo) y úsala para establecer otro ajuste utilizando la clave y el valor de las entradas.

    Finalmente, verifica que el Singleton esté funcionando correctamente:

    • Imprime "Same instance: true" o "Same instance: false" basándote en si ambas referencias apuntan al mismo objeto (usa === para comparar)
    • Imprime "Settings count: [count]" mostrando el número total de ajustes almacenados (usa count() en el resultado de getAll())
    • Imprime "App name: [value]" mostrando el ajuste app_name recuperado a través de la segunda referencia

Este desafío demuestra el beneficio principal del Patrón Singleton: no importa cuántas veces llames a getInstance(), siempre obtendrás el mismo objeto, asegurando que todas las partes de tu aplicación compartan el mismo estado de configuración.

Pruébalo tú mismo

<?php

require_once 'Config.php';

// Leer entrada
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: Obtener la instancia de Config y establecer "app_name" a "MyApp"

// TODO: Obtener una segunda referencia a Config usando getInstance() de nuevo

// TODO: Usar la segunda referencia para establecer el ajuste usando $key y $value de la entrada

// TODO: Verificar que el Singleton está funcionando:
// - Imprimir "Same instance: true" o "Same instance: false" basado en la comparación ===
// - Imprimir "Settings count: [count]" mostrando el total de ajustes
// - Imprimir "App name: [value]" mostrando app_name recuperado a través de la segunda referencia

?>
quiz iconPonte a prueba

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