Patrón Factory Práctica


La creación de un nuevo objeto requiere de una serie de pasos, configuraciones e incluso puede ser necesario crear objetos de alguna subclase. Este problema se ve incrementado si el número de objetos (de la misma clase) a crear, es elevado. El problema entonces: ¿Cómo crear objetos complejos de forma fácil, rápida y sin posibilidad de errores?
La solución a este problema puede ser la siguiente: crear un método de clase (o una función) que se encargue de crear la instancia, configurar los nuevos objetos e incluso de crear objetos dependientes de otras clases. De este modo la llamada será simple, independientemente de la complejidad que tenga esa clase en si para ser instanciada.

Esta solución es la que nos brinda el patrón "Factory". El cual hace uso de una Clase con la responsabilidad de crear objetos de otras clases. No delega en subclases y sus métodos pueden ser estáticos. Creando así objetos de un tipo determinado en tiempo de ejecución.

¿Qué pasaría en caso de no utilizar el patrón Factory si es necesario cambiar la estructura de los objetos? habría que ir objeto por objeto de la clase reformada cambiando su estructura y adaptándolo a su nueva forma, la pérdida de tiempo que esto ocasionaría se incrementa por el número de objetos que se crean en la aplicación y la complejidad de estos.

Si se utiliza un método regido por "Factory" para crear los objetos, la adaptación de estos sería por la modificación única en el método que crea la instancia, con lo cual la pérdida de tiempo es mínima, sin hablar de la posibilidad de errores que se pueden cometer si el número de objetos a modificar es elevado.

Se crea una Clase abstracta para crear métodos para acceder a las bases de datos independientemente de la fuente de datos, de la cual heredan las clases hijas que implementan los métodos según lo que estás necesiten. Declarando una interfaz para las operaciones de creación de productos abstractos.

<?php

abstract class ConnectionDB
{
      /**
       * Nombre o IP del servidor de la bd
       */
      protected $host;
      /**
       * Nombre del usuario de la bd
       */
      protected $user;
      /**
       * Password del usuario
       */
      protected $pwd;
      /**
       * Nombre de la base de datos
       */
      protected $database;
      /**
       * Sentencia sql
       */
      protected $sql;
      /**
       * Tabla que representa los datos de una tabla, resultado
       * de un SELECT
       */
      protected $responseSql;
      /**
       * Manejador de la conexion de la bd
       */
      protected $link;
      /**
       * Numero de registros afectados despues de una sentencia sql
       */
      protected $num_reg;
      /**
       * Constructor
       */
      public function _construct( ) {

      }

      /**
       * conectarse a la base de datos
       *
       */

      abstract public function connect( );
      /**
       * consultar a la bd - select
       */
      abstract  public function consult( );

      /**
       * actualizar la bd: insert, delete, update
       */
      abstract  public function update( );
      /**
       * extraer los datos de una fila
       * @param string response, la consulta
       * @param int row, numero de fila
       * @return string
       */
      abstract public function fetch_row( $response,  $row );
      /**
       * Extrae la informacion de un campo
       *
       * @param string $field, nombre del campo
       * @param int $row, numero de fila
       */
      abstract function fetch_field($field, $row);

      /**
       * desconectarse de la bd
       */
      abstract public function disconnect( );

      /**
       * Establecer el atributo sql
       */
      abstract public function setSql( $sql );

      /**
       * devolver el numero de registros afectados
       */
      abstract public function getNumReg( );

      /**
       * devolver la cadena sql
       */
      abstract public function getResponseSql( );
      /**
       * Retorna la clausula limit del select
       */
      abstract public function limit($sizePag, $limitInf);
}
?>

Se crea ahora un archivo conf donde se especifica que base de datos va a utilizar nuestra aplicación.

<?php

$CFG_HOST = "localhost";
$CFG_USER = "root";
$CFG_DBPWD = "";
$CFG_DBASE = "bdBeauty";
$CFG_DBASE_TYPE = "mysql";    /* ß Aquí especificamos la Base de Datos.*/

$CFG_SIZE_PAGE=10;

?>


Se crea la clase Fábrica por método.  La cual devuelve una conexión de una fuente de datos  particular, según la tipo de base de datos que se vaya a usar en la aplicación.



<?php
require_once 'mysql.lib.php';
require_once 'connectiondb.lib.php';

class FactoryDB
{
      /**
       *
       * @param String databaseType
       * @return ConnectionDB
       * @access public
       */
      public static function getConnection( $databaseType ) {
            if (!strcmp($databaseType,"mysql")){
                  return new Mysql();
            }
            if (!strcmp($databaseType,'pgsql')){
                  return new Pgsql();
            }
      }
}
?>

Se crea cada una de  las clases utilizadas para controlar las operaciones de gestión con una Base de Datos, en este caso en Mysql.  Interactuando directamente con SQL y con el motor de bases de datos.  Hereda de la clase abstracta ConnnectionDB, implementando según lo que esta necesite de lo especificado en la clase padre.


<?php

require_once 'connectiondb.lib.php';

class Mysql extends ConnectionDB {

      /**
       * Constructor de la clase
       */
      function __construct() {

            global $CFG_HOST, $CFG_USER, $CFG_DBPWD, $CFG_DBASE;
            $this->host = $CFG_HOST;
            $this->user = $CFG_USER;
            $this->pwd = $CFG_DBPWD;
            $this->dataBase= $CFG_DBASE;
            $this->sql = "";
            $this->responseSql = "";
            $this->link = null;
            $this->numReg = 0;
      }

      function connect() {

            if (($this->link = mysql_connect($this->host, $this->user, $this->pwd)) != null) {
                  mysql_select_db($this->dataBase) or die('No pudo seleccionarse la BD.');
                  return($this->link);
            } else {
                  print "<b>Error:</b> No se ha podido establecer una conexion con el servidor de Bases de Datos $CFG_HOST";
             return (null);
            }
      }

      function consult() {
            $this->responseSql = mysql_query($this->sql);
            $this->numReg = mysql_num_rows($this->responseSql);
      }

      function update() {
            $this->responseSql = mysql_query($this->sql);
      }

      function fetch_field($field, $wrow) {
            //En el caso de Mysql no necesita la fila
            $fila=mysql_fetch_row($this->responseSql);
            return  $fila[$field];
      }
       
      function fetch_row($response, $row){
            //En el caso de Mysql no necesita la fila
            $fila = mysql_fetch_row($response);
            return $fila;
      }

      function disconnect() {
            mysql_close($this->link);    // Cerrar la conexion
      }

      function setSql($sql){
            $this->sql = $sql;
      }

      function getNumReg(){
            return $this->numReg;
      }

      function getResponseSql(){
            return $this->responseSql;
      }

      public function limit($sizePag, $limitInf){
            return " LIMIT ".$limitInf.",".$sizePag;
      }
}
?>


Se crea cada una de  las clases utilizadas para controlar las operaciones de gestión con una Base de Datos, en este caso en Postgres.  Interactuando directamente con el motor de bases de datos.  Hereda de la clase abstracta ConnnectionDB, implementando según lo que esta necesite de lo especificado en la clase padre.

<?php
require_once 'connectiondb.lib.php';

class Pgsql extends ConnectionDB {

      /**
       * Constructor de la clase
       */
      function __construct() {

            global $CFG_HOST, $CFG_USER, $CFG_DBPWD, $CFG_DBASE;
            $this->host = $CFG_HOST;
            $this->user = $CFG_USER;
            $this->pwd = $CFG_DBPWD;
            $this->database= $CFG_DBASE;
            $this->sql = "";
            $this->responseSql = "";
            $this->link = null;
            $this->numReg = 0;
      }

      function connect() {
            $cad_cx = "host=".$this->host." port=5432 dbname=".$this->database." user=".$this->user." password=".$this->pwd;
            if (($this->link = pg_connect($cad_cx)) != null) {
                  return($this->link);
            }
            else{
                  print "<b>Error:</b> No se ha podido establecer una conexion con el servidor de Bases de Datos $CFG_HOST";
                  return (null);
            }
      }

      function consult() {
            $this->responseSql = pg_query($this->link, $this->sql);
            $this->numReg = pg_num_rows($this->responseSql);
      }

      function update() {
            $this->responseSql = pg_query($this->sql);
            $this->numReg = pg_num_rows($this->responseSql);
      }

      function fetch_field($field,$row) {
            //En el caso de Mysql no necesita la fila
            return (pg_fetch_result($this->responseSql,$row,$field));
      }

      function fetch_row($response, $row){
            //En el caso de Mysql no necesita la fila
            $fila= pg_fetch_row ($response, $row);
            return $fila;
      }

      function disconnect() {
            pg_Close();
      }

      function setSql($sql){
            $this->sql = $sql;
      }

      function getNumReg(){
            return $this->numReg;
      }

      function getResponseSql(){
            return $this->responseSql;
      }
      public function limit($sizePag, $limitInf){
            return " LIMIT ".$sizePag." OFFSET ".$limitInf;
      }
}
?>



Donde desde el modulo usuarios se realiza una solicitud de coneccion para poder abstraer la información de la base de datos referente a este modulo.

require_once("lib/factorydb.lib.php");
require_once("lib/mysql.lib.php");
require_once('modules/user/model/user.php');

class UserDB {
      /**
       * Conexion con la bd
       */
      private $conn;
      /**
       * Constructor
       *
       */
      function __construct() {
            global $CFG_DBASE_TYPE;
            $this->conn = FactoryDB::getConnection($CFG_DBASE_TYPE);
      }
}