El patrón singleton con PHP

Algunas veces nos interesa tener controlada la creación de objetos por motivos como por ejemplo el ahorro de memoria. Una forma de hacer esto es utilizando el patrón de diseño "Singleton". Vamos a estudiar un ejemplo en PHP para ver su utilidad, funcionamiento e implementación.

Un claro ejemplo de la utilidad de este patrón sería una clase para trabajar con bases de datos. Si cada vez que necesitemos conectarnos tenemos que crear una instancia del objeto, estaríamos aumentando el consumo de memoria de nuestra aplicación de una manera innecesaria. Lo que normalmente suele hacer la gente es utilizar una variable global que sería una instancia de ese objecto, pero el uso de variables globales no es recomendado por multitud de razones que darían para otro "Post".

Para conseguir nuestro objetivo lo primero que tenemos que hacer es no permitir crear instancias del objeto, para esto basta con "ocultar" el constructor declarándolo como "private". Lo siguiente que necesitamos es crear un método estático que nos devuelva una instancia de ese objeto, si existe una ya creada la devolvemos y si no creamos una nueva.

Veamos un ejemplo de implementación:

	class Database {
		static private $instance = null;
		
		private function __contruct() {}
		
		public static function getInstance() {
			if (self::$instance == null) {
				self::$instance = new Database();
			}
			return self::$instance;
		}
		
		public function connect($dsn) {
			...
		}
		
		public function query($sql) {
			...
		}
		
		public function executeQuery() {
			...
		}
		
		public function getResult() {
			...
		}
		
		public function disconnect() {
			...
		}
	}


Éste sería un prototipo de una clase para trabajar con una base de datos. Como podemos ver, ya no podremos hacer "$db = new Database();", por lo que nos aseguramos el ahorro de memoria. En su lugar para obtener el objeto que deseamos tendremos que hacer:

	...
	$db = Database::getInstance();
	$db->connect($dsn);
	...
	...


Siempre que llamemos al método estático "getInstance()" se comprobará que no exista ya una instancia de este objeto, si no existe crearemos una, la guardaremos como una propiedad estática de la clase y la devolveremos, muy simple.

Otra forma de ejecutar el código anterior sin tener que inicializar ninguna variable:

	...
	Database::getInstance()->connect($dsn);
	...


Como se puede apreciar, utilizando este patrón adecuadamente, a parte de ahorrar memoria, tendríamos un código más limpio y libre de variables globales, que pueden ser modificadas por accidente en otros procesos

Comentarios

Comentario de Pablo - 24 de Junio de 2011 - 12:27
Muy útil! gracias !!
Comentario de Ramón - 24 de Junio de 2011 - 12:37
Pues no se si lo acabo de entender, le daré mas vueltas a ver.
Comentario de Jose - 13 de Enero de 2013 - 12:14
No esta completo no ayuda de mucho...
Comentario de Emanuel Cerron - 07 de Febrero de 2013 - 14:39
puedes compartir la clase completa > Database
Comentario de Bruz - 27 de Abril de 2013 - 07:51
Muchas gracias!! Un ejemplo PRÁCTICO y sencillo para novatos, algo no tan fácil de encontrar como parece.
Comentario de ANGEL - 18 de Enero de 2014 - 20:58
Gracias por tu aporte, me sirvio de utilidad
Comentario de Agustín Sardón - 27 de Agosto de 2014 - 00:19
Muy útil y sin complicarlo innecesariamente. Yo lo utilizaba en una clase Conexion, precisamente para obtener una conexión a una base de datos. Me aproximaba bastante pero me faltaba el constructor privado y vacio. ¿Otra forma de evitar que se pueda instanciar la clase podría ser declararla como abstracta? Muchas gracias por el post
Ha habido un error en el envío
Comentario enviado. Será revisado por la moderación antes de ser publicado.

Deja tu comentario

Tu nombre:
Tu email:
Tu comentario: