2010-01-20 16 views
10

Ahora estoy trabajando con clases y objetos de PHP. En esta pregunta, los nombres de los campos y métodos están formados solo para que tenga una idea de lo que estoy hablando.¿Patrón de registro o Singleton en PHP?

Está relacionado con el uso de patrones de diseño singleton y de registro.

Ahora digamos que necesito acceder a un objeto de base de datos, objeto de caché, objeto de configuración principal, objeto de sesión en casi todas las demás clases que necesitaré para tener acceso a ellas. SO usaría un registro para almacenar los 4 de esos objetos en 1 objeto de clase de registro. Entonces podría easiyl simplemente pasar mi 1 objeto a cualquier otro objeto que necesite acceder a ellos. Eso suena muy bien hasta ahora, pero ¿qué sucede si tengo algunas clases que no necesitan todos los 4 de esos objetos, qué sucede si SÓLO necesito acceder al objeto Base de datos o al objeto Session en algunas de mis otras clases? Para el desempeño, ¿sería mejor usar un singleton dentro de estos otros objetos o sería lo mismo continuar y usar mi registro en estos?

No sé lo suficiente cómo funcionan los objetos en PHP para saber si habría algún tipo de ganancia de rendimiento (menos uso de memoria, uso de la CPU, tiempo de carga).

Así que cualquier persona con experiencia en esto tal vez pueda decirme si habría alguna ganancia usando uno u otro, estoy en la etapa en la que puedo usar el éter sin afectar el tiempo de producción ni nada. Me gustaría usar el mejor método si puedo ahora.

+0

De hecho, encontré una pregunta hace un momento que es básicamente el mismo http://stackoverflow.com/questions/1967363/registry-or-singleton – JasonDavis

+0

Tome en cuenta que si usted está utilizando PHP4 o PHP5 ... objetos funcionan de manera muy diferente, y en PHP4 palabras clave como 'estático' no son compatibles. Lo más probable es que esté utilizando 5, pero si desea ingresar al OOP pertinente, debe estar seguro. –

Respuesta

3

Eso depende de su aplicación. Si aún necesita 3 de las 4 clases, sería más ideal usar el Registro que manejar el 3 de forma independiente solo porque no necesita el cuarto. Cargar las clases perezosamente sería un enfoque para reducir la huella de memoria, pero luego debe indicarle al registro cuándo crear los objetos y eso no es muy diferente de manejar los singletons. De forma alternativa, podría crear un constructor de n parámetros o usar una matriz para indicar a su Registro qué clases instanciar durante la construcción.

class Registry { 
    public $class1; 
    public $class2; 

    function __construct($uses) { 
     foreach($uses as $class) { 
      $this->{$class} = new {$class}(); 
     } 
    } 

} 

A continuación, ejemplifique su Registro especificando qué clases instanciar.

$reg = new Registry(array('class1')); 

Obviamente, querría que su constructor maneje cero parámetros para dar cuenta de la creación de instancias de todas las clases de forma predeterminada.

+0

Esa es una idea genial, gracias. Debo mencionar, incluso si 1 clase solo necesita 1-2 de los objetos, ya hay otra clase llamada en la misma página que probablemente también tenga los 4 objetos ya inyectados en ella. No estoy seguro de cómo funciona la memoria, por lo que ya puede estar cargada 1 vez. No sé si la memoria almacenará los objetos más de una vez en ram o no. – JasonDavis

+0

Mi ejemplo de código supone que sus clases se aferran a su propia instancia de su Registro. Esto significaría mucho exceso de memoria si tiene más de una clase por página utilizando los mismos objetos de registro comunes. Si está utilizando una instancia estática/global, entonces su implementación sería diferente a la de mi ejemplo, pero aún podría hacerse. Esto también significaría compartir los mismos objetos en la memoria en todas las clases, lo que sería mucho más eficiente. Para que mi ejemplo funcione de esta forma, cree una función Registry :: initInstances() en lugar de utilizar el constructor. –

+0

Ok, eso es lo que estaba pensando, supongo que estamos en la misma página, algo así como el método de dbemerlin a continuación. – JasonDavis

4

Puede implementar la carga diferida a cargar sólo los objetos que realmente necesita:

class Registry 
{ 
    private static $database = null; 

    private static function connectDatabase($key) 
    { 
     [... do connection stuff ...] 
    } 

    public static function getDatabase($key) 
    { 
     if (Registry::$database == null) 
     { 
      Registry::connectDatabase($key); 
     } 
     return Registry::$database; 
    } 
} 

El código para registrar los parámetros de conexión de base de datos se deja como ejercicio para el lector.

+3

¿No es esto solo un singleton? – JasonDavis

+0

No sé qué más se puede llamar singleton –

+0

Este es el patrón singleton puro, que no es realmente un patrón, sino que es anti-patrón. –

1

Quizás este es el patrón de Singleton-Registry adecuado. OFC, puede implementar cosas diferentes, SplFixedArray, interfaz ArrayAccess y otros. Además, no está mal agregar la destrucción y destruir los objetos internos para garantizar que no haya fugas.

class oRegistry{ 
    private static $instance = null; 

    private $storage = array(); 

    private function __construct(){} 

    private function __clone(){} 

    public static function getInstance(){ 
     if(self::$instance === null){ 
     self::$instance = new self(); 
     } 
     return self::$instance; 
    } 

    public function attach($name, $o) { 
     if(true === isset($this->storage[$name])) { 
      throw new Exception('The instance with name '.$name.' already exists in registry.'); 
     } 
     if(!empty($name)) { 
      $this->storage[ $name ] = $o; 
     } 
    } 

    public function detach($name){ 
     if(isset($this->storage[ $name ])) { 
      $this->storage[ $name ] = null; 
      unset($this->storage[ $name ]); 
     } 
    } 

    public function get($name){ 
     if(false === isset($this->storage[$name])) { 
      throw new Exception('Invalid instance requested'); 
     } 
     return $this->storage[ $name ]; 
    } 
} 

// usage example 
$storage = oRegistry::getInstance(); 
$obj = new stdClass; 
$obj2 = new stdClass; 
$obj->test1 = 'test'; 
$obj2->test2 = 't2'; 

$storage->attach('test1', $obj); 
$storage->attach('test2', $obj2); 

$got = $storage->get('test2'); 
var_dump($got); // object(stdClass)#3 (1) { ["test2"]=> string(2) "t2" } 

$storage->detach('test2'); 
$got = $storage->get('test2'); 
var_dump($got); // bool(false) 
Cuestiones relacionadas