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 sola instancia durante todo el ciclo de vida de tu 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 una base de datos, un gestor de configuración o un registrador. Crear múltiples instancias de estos desperdiciaría recursos o provocaría un comportamiento incoherente.

Así es como se implementa un Singleton en PHP:

<?php
class Database {
    private static ?Database $instance = null;
    
    private function __construct() {
        // El constructor privado impide 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";

Salida:

Same instance

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

Para hacer que el Singleton sea realmente infalible, también debes impedir 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

Construyamos un gestor de configuración usando el patrón Singleton. En las aplicaciones reales, normalmente quieres una única fuente de verdad para los ajustes de configuración: tener varios objetos de configuración podría provocar un comportamiento incoherente 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 única instancia
    • Impedir 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 usando la clave y el valor de las entradas.

    Finalmente, verifica que Singleton funciona correctamente:

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

Este desafío demuestra el beneficio principal del patrón Singleton: sin importar cuántas veces llames a getInstance(), siempre obtendrás el mismo objeto, lo que garantiza 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: Obtén la instancia de Config y establece "app_name" a "MyApp"

// TODO: Obtén una segunda referencia a Config usando getInstance() de nuevo

// TODO: Usa la segunda referencia para establecer la configuración usando $key y $value de la entrada

// TODO: Verifica que el Singleton funcione:
// - Print "Same instance: true" or "Same instance: false" based on === comparison
// - Print "Settings count: [count]" showing total settings
// - Imprime "App name: [value]" mostrando app_name obtenido 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

Practica por tu cuenta: Compilador de PHP online