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 instanceEl 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");
}
Desafío
FácilConstruyamos 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 claseConfigque 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): voidpara almacenar un ajuste - Incluir un método
get(string $key): ?stringque devuelva el valor de una clave, onullsi la clave no existe - Incluir un método
getAll(): arrayque 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 (usacount()sobre el resultado degetAll()) - Imprime
"App name: [value]"mostrando el ajuste app_name recuperado mediante la segunda referencia
- Imprime
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
?>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 la POO
Archivos externosIntroducción a la POOClases frente a objetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Repaso: calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasRepaso - Jerarquía de empleados7Encapsulación
Público, protegido, privadoModificadores de acceso en profundidadGetters y settersOcultación de la informaciónPromoción del constructor (8.0)Repaso: sistema de registros de estudiantes10Conceptos avanzados de OOP
Composición vs. herenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibras (PHP 8.1)Análisis profundo de la clonación de objetosGeneradores e iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Namespaces y carga automática
Introducción a los NamespacesLa palabra clave useEstándar de carga automática PSR-4Autoloader de ComposerRepaso: proyecto organizado5Interfaces y contratos
Introducción a las interfacesImplementación de interfacesImplementación de múltiples interfacesInterfaces vs. clase abstractaTipado con interfacesRepaso - 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 __unserializeRepaso: 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)Repaso: gestor de cuentas bancarias6Polimorfismo
Repaso de la sobrescritura de métodosPolimorfismo mediante interfacesAnotaciones de tipo y tipos uniónEnlace estático tardíoRepaso: procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos entre TraitsMétodos abstractos en TraitsTraits frente a la herencia12Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de PHP online