Php Patron singleton y la clase para conectar con base de datos CBaseDatos

Php Patron singleton y la clase para conectar con base de datos CBaseDatos

Se habla mucho sobre el patron de diseño singleton pero se ve pocos ejemplos orientativos sobre su utilización en un proyecto real. Voy a poner un ejemplo real. En el proceso de creación de "The framework", haciendo una depuracion del codigo vi que se creaba una instancia de la clase de conexion (CBaseDatos) por cada objeto de cualquier modelo que construia. En muchos casos hasta 16 instancias de conexiones, para una funcion que utilizaba 3 Modelos. //MPais, MProvincia y MCiudad son clases que extienden de MainModel function lista_detallada_paises() { $oPais = new MPais(); $oProvincia = new MProvincia(); $oCiudad = new MCiudad(); ..... } Parte del código del modelo padre MainModel class MainModel { ... protected $_oBD; protected $_sTabla; protected $_id; public function __construct($sNombreTabla, $id) { //Esta es la linea que creaba una instancia por cada objeto //construido ejemplo: MPais(), MProvincia()... $this->_oBD = new CBaseDatos(); $this->_oBD->conectar(); $this->_sTabla = $sNombreTabla; $this->_id = $id; //Funcion equivalente a var_dump bug($this->_oBD); } ... Al ejecutar la funcion lista_detallada_paises() esta mostraba el numero de recursos oBD creados. Como se han dado cuenta esto es ineficiente porque con una instancia de conexion (un objeto CBaseDatos) compartida por el resto era suficiente. Es aqui cuando decido pasar la clase CBaseDatos al patrón singleton. /** * @author Eduardo Acevedo Farje * @web www.eduardoaf.com */ class CBaseDatos //Tipo Singleton { //objeto resource que indicara si se ha conectado private $_oLinkId; private $_sServidor; private $_sNombreBD; private $_sUsuario; private $_sClave; private $_sMensaje; //Almacenara un objeto de tipo CBaseDatos private static $_oSelf = null; private function __construct() { $this->_sServidor = sServidorBD; $this->_sNombreBD = sNombreBD; $this->_sUsuario = sUserBD; $this->_sClave = sClaveBD; $this->_sMensaje = ""; } /** * Este es el pseudo constructor singleton * Comprueba si la variable privada $_oSelf tiene un objeto * de esta misma clase, sino lo tiene lo crea y lo guarda */ public static function get_instancia() { //Si no hay instancia de CBaseDatos //en la variable estatica $_oSelf if( !self::$_oSelf instanceof self ) { //Se crea un objeto de CBaseDatos guardandolo //en la varialbe estatica //new self ejecuta __construct() self::$_oSelf = new self; } //Se devuelve el objeto creado return self::$_oSelf; } /** * Realiza la conexion y devuelve el resultado * @return true si hubo exito en la conexion */ public function conectar() { //VERIFICAMOS LA CONEXION CON MYSQL //rCon es tipo resource si tiene exito y guarda un "link identifier" //sino guarda un false $oMysqlConnect = mysql_connect ( $this->_sServidor, $this->_sUsuario, $this->_sClave ); //si no es tipo resource es q no ha tenido exito la conexion if(!is_resource($oMysqlConnect)) { $this->_sMensaje = "ERROR: No se puede conectar a la base de datos..! ".$this->_sNombreBD; //Lanza la excepcion y se sale del procedimiento throw new Exception($this->_sMensaje); die; } //Guardamos el id del recurso conectado $this->_oLinkId = $oMysqlConnect; //VERIFICAMOS QUE EXISTA LA BASE DE DATOS EN EL MOTOR $bExisteBD = mysql_select_db($this->_sNombreBD, $oMysqlConnect); //si no se pudo encontrar esa BD lanza un error if(!$bExisteBD) { $this->_sMensaje = "ERROR: No se puede usar la base de datos..! ".$this->_sNombreBD; //Lanza la excepcion y se sale del procedimiento throw new Exception($this->_sMensaje); die; } else //Si se conectÓ { $this->_sMensaje = "SE CONECTO CON EXITO"; mysql_set_charset('utf8',$this->_oLinkId); } return true; } private function get_servidor() { return $this->_sServidor; } public function get_usuario() { return $this->_sUsuario; } private function get_clave() { return $this->_sClave; } public function get_mensaje() { return $this->_sMensaje; } public function get_nombre_bd() { return $this->_sNombreBD; } public function get_link_id() { return $this->_oLinkId; } } Despues de la conversión a singleton, esta es la nueva forma de instanciar un objeto de CBaseDatos. class MainModel { ... protected $_oBD; protected $_sTabla; protected $_id; public function __construct($sNombreTabla, $id) { //La linea antigua //$this->_oBD = new CBaseDatos(); //Linea en singleton $this->_oBD = CBaseDatos::get_instancia(); $this->_oBD->conectar(); $this->_sTabla = $sNombreTabla; $this->_id = $id; //Funcion equivalente a var_dump bug($this->_oBD); } ... Como se ve ya no creamos un objeto de CBaseDatos con el tipico constructor "new CBaseDatos()" sino que lo hacemos utilizando el metodo estatico publico que nos devuelve un objeto de este tipo. Si bien cada modelo cuando es construido tiene su atributo propio $_oBD este apunta a la única instancia de conexión. Tienes algun otro ejemplo real de como utilizar este patrón?

Autor: Eduardo A. F.
Publicado: 22-04-2011 21:17
Actualizado: 02-07-2011 15:41