miércoles, 29 de febrero de 2012

Patrones de diseño II - Singleton

Aquí venimos de nuevo con un nuevo patrón de diseño, el denominado singleton. Este patrón nos servirá para cuando queremos que un objeto tenga una sola y única instancia en toda la aplicación, como por ejemplo al conexión a la base de datos.
La conexión a bases de datos consume muchos recursos del servidor, por lo que nos interesa, conectar una sola vez y realizar todas las consultas necesarias, además de esta forma, nos evitamos tener que crear múltiples objetos que también hacen que la aplicación ocupe más memoria.

A continuación podéis ver la estructura básica de un singleton y después lo explicaremos detalladamente.

/**
 * Objeto del cual deseamos tener una sola instancia
 * en toda la aplicación.
 */
class mi_objeto
{
        /**
         * Aquí se almacenará la única instancia existente
         * del propio objeto.
         *
         * @var mi_objeto
         */
        private static $instancia;

        /**
         * Constructor para la creación de una instancia
         * del objeto.
         */
        private function __construct(){}

        /**
         * Método que siempre devuelve la misma instancia
         * del objeto.
         */
        public static function getInstance()
        {
                if ( !self::$instancia )
                {
                        self::$instancia = new self;
                }

                return self::$instancia;
        }
}


La primera parte y fundamental del código es la variable $instancia.
private static $instancia;
Esta variable almacenará la única instancia disponible en toda la aplicación. Esta variable es estática, ya que debe estar siempre accesible. Si no sabéis que es o para que sirve una variable estática, os recomiendo ver los ejemplos disponibles en la documentación oficial de php.

Más adelante nos encontramos con algo que al principio parece extraño y es que el constructor de la clase es privado. Como hemos dicho solo queremos una instancia en toda la aplicación y es por eso que el constructor es privado, para que nadie pueda realizar por desconocimiento o despiste algo como
$variable = new mi_objeto();
ya que al ser el constructor privado, esto lanzaría un error en la aplicación y evitaría la creación descontrolada de objetos.

Llegados a este punto muchos se preguntarán como se hace entonces para poder crear una un objeto, teniendo el operador new bloqueado. Pues la respuesta es sencilla como ejecutar el método getInstance.
$obj = mi_objeto::getInstance();
Como puede verse en el código del método getInstance, lo que hace es primero que todo comprobar si el objeto ha sido creado anteriormente y en caso de que no haya sido creado anteriormente lo crea y lo devuelve. A partir de este momento, todas las veces que queramos obtener un objeto de la clase mi_objeto, ya no se devolverá una nueva instancia, si no que se obtendrá la generada por primera vez.

A continuación dejo un ejemplo práctico de una clase singleton, con un ejemplo de su funcionamiento. Probad a jugar un poco con ella y pensar posibles usos.
/**
 * Objeto del cual deseamos tener una sola instancia
 * en toda la aplicación.
 */
class mi_objeto
{
        /**
         * Aquí se almacenará la única instancia existente
         * del propio objeto.
         *
         * @var mi_objeto
         */
        private static $instancia;

        /**
         * Variable para almacenar un número
         */
        public $numero;

        /**
         * Constructor para la creación de una instancia
         * del objeto.
         */
        private function __construct(){}

        /**
         * Método que siempre devuelve la misma instancia
         * del objeto.
         */
        public static function getInstance()
        {
                if ( !self::$instancia )
                {
                        self::$instancia = new self;
                }

                return self::$instancia;
        }
}

//Creo un objeto y le asigno un numero
$var = mi_objeto::getInstance();
$var->numero = 23;

//Elimino el contenido de la varible.
$var = null;

//Vuelvo a obtener una instancia del objeto.
//Al ser un singleton lo que se obtendrá es la
//misma instancia que estaba en $var
$nueva_var = mi_objeto::getInstance();

//Imprimirá el número 23
echo $nueva_var->numero;

Os dejo tanto el código base del singleton como del ejemplo para su descarga.

No hay comentarios:

Publicar un comentario