Como Jorge mencionó en su último post, andamos re-diseñando la arquitectura de gelato cms, para en un par de versiones mudarlo completamente a PHP5 para obtener ventaja de su poderoso motor de OOP y poder hacer un mejor uso de los patrones de diseño.
Por lo que comenzaré con una serie de posts sobre como implementar patrones de diseño con PHP5 y un par de ejemplos un poco más adelante de como aplicarlos en “la vida real” de nuestros proyectos.
El primer patrón con el que iniciaré es el patrón Singleton, el cual considero como la base de la implementación exitosa de muchos patrones.
La teorÃa nos dice lo siguiente:
El patrón de diseño Singleton (instancia única) está diseñado para restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto.
Su intención consiste en garantizar que una clase sólo tenga una instancia y proporcionar un punto de acceso global a ella.
Por lo que al usar el patrón Singleton nos aseguramos que SOLO tendremos una misma instancia de nuestra clase.
¿Cómo hacerlo con PHP5?
< ?php
class Singleton {
// Una propiedad para tener la instancia de la clase
private static $instancia;
// Desde aqui se obtiene la instancia OJO con el static
public static function getInstance () {
if (!isset(self::$instancia)) {
$obj = __CLASS__;
self::$instancia = new $obj;
}
return self::$instancia;
}
// Se crean los metodos requeridos
public function accion() {
echo "Objeto unico";
}
// Privado se previene la creacion via new
private function __construct() { }
// Para evitar la clonacion de este objeto
private function __clone() {
throw new Exception('No se permite clonar');
}
}
?>
-
< ?php
-
class Singleton {
-
-
// Una propiedad para tener la instancia de la clase
-
-
-
// Desde aqui se obtiene la instancia OJO con el static
-
public
static function getInstance
() {
-
if (!
isset(self::
$instancia)) {
-
$obj = __CLASS__;
-
self::$instancia = new $obj;
-
}
-
return self::$instancia;
-
}
-
-
// Se crean los metodos requeridos
-
public function accion() {
-
-
}
-
-
// Privado se previene la creacion via new
-
private function __construct() { }
-
-
// Para evitar la clonacion de este objeto
-
private function __clone() {
-
throw new Exception(‘No se permite clonar’);
-
}
-
}
-
?>
Y para utilizarlo:
< ?php
include("singleton.php");
$prueba = Singleton::getInstance();
$prueba->accion();
?>
-
< ?php
-
include("singleton.php");
-
$prueba = Singleton::getInstance();
-
$prueba->accion();
-
?>
Nos leemos en la siguiente entrega
marcoss
March 24, 2008 at 9:25 pm
No me convence mucho como instancias, creo que esto:
public static function getInstance () {if (!isset(self::$instancia)) {
$obj = __CLASS__;
self::$instancia = new $obj;
}
return self::$instancia;
}
podrÃa simplificarse en:
public static function getInstance () {self::$instancia =& $this;
}
Vos que sos mas conocedor, fijate si tiene alguna desventaja que no estoy viendo.
pecesama
March 25, 2008 at 11:50 am
marcoss muy buena pregunta, trataré de responder lo mejor que pueda, pero se me pude ir algo, tú dime si se me esta escapando algo ahora a mi
Creo que hay un poco de confusión, el & se usaba en PHP4 para pasar variables u objetos por referencia, pero en PHP5 ya todo es por referencia, por lo que el & deja de ser útil, y me parece que usar el
self::instanciaseria mezclarlo, más bien algo asÃ:$instancia =& new $class;En la forma en que me muestras el método
getInstanceno funcionarÃa correctamente ya que no hay validaciones de que si no existe previamente el objeto cree uno nuevo y el método deberÃa llevar un & en el nombre, quedarÃa algo asà en PHP4 ese método:function &getInstance ($class) {
static $instancia;
if (!isset( $instancia )) {
$instancia =& new $class;
}
return $instancia;
}
Y el método en PHP5 se podrÃa simplificar de la siguiente manera:
public static function getInstance () {
if (!isset(self::$instancia)) {
self::$instancia = new self();
}
return self::$instancia;
}
marcoss
March 26, 2008 at 9:59 am
Ya me di cuenta donde estaba mi error, lo peor es que creo que lo probe antes de comentar y se ve que funcionaba… pero ahora veo que no tiene sentido, en fin, eso pasa por dejar un comentario cuando deberÃa estar durmiendo
La segunda opción está mas clara igual, “self::$instancia = new self();”
pecesama
March 26, 2008 at 7:38 pm
Todo claro ahora
jhon
May 31, 2008 at 6:14 pm
bueno realmente probe el ejemplo y funciono bien el problema surge cuando incluyo “singleton” el la clase A y tambien lo hago en B;
hasta hay todo bien pero cuando trato de incluir B en A me dice que no puedo redeclarar “singleton”..mi pregunta de que manera puedo hacerlo pues necesito manejar las clase…grasias
pecesama
May 31, 2008 at 8:19 pm
jhon eln la segunda parte de este patron explico como usarlo http://www.pecesama.net/weblog/2008/03/25/patron-singleton-parte-ii/
allende
January 21, 2010 at 7:44 am
Muy claro el ejemplo, solo tengo una duda
Si (corrigeme si me equivoco por favor o aclaramelo) “__CLASS__” regresa un string con el nombre de la clase, como es posible que funcione en la siguiente linea la variable $obj.
$obj = __CLASS__;
self::$instancia = new $obj;
Es decir si hiciera:
self::$instancia = new “Singleton”;
No funciona (salvo que quite las comillas), me deja un poco perdido eso, ademas de que usar __CLASS__ después del new tampoco me funciona:
self::$instancia = new __CLASS__;
Supongo que usar “self” o “Singleton” (sin comillas) es equivalente al uso de “$obj = __CLASS__” y luego:
self::$instancia = new $obj;
Un saludo y gracias.