2010-01-20 6 views
10

Je travaille avec des classes et des objets PHP maintenant. Dans cette question, les noms des champs et des méthodes sont inventés juste pour que vous ayez une idée de ce dont je parle.Registre ou motif Singleton en PHP?

Il est lié à l'utilisation des modèles de conception de singleton et de registre. Maintenant, disons que je dois accéder à un objet Database, un objet Cache, un objet Core Settings, un objet Session dans presque toutes les autres classes auxquelles j'aurai besoin d'accéder. Donc, je voudrais utiliser un registre pour stocker tous les 4 de ces objets dans 1 objet de classe de registre. Je pourrais alors simplement passer mon objet dans un autre objet qui doit y accéder. Donc ça sonne bien jusqu'ici mais que se passe-t-il si j'ai des classes qui n'ont pas besoin de tous ces 4 objets, que dois-je faire pour accéder à l'objet Database ou à l'objet Session dans certaines de mes autres classes? Pour perfromance serait-il préférable de simplement utiliser un singleton à l'intérieur de ces autres objets ou serait-il le même d'aller de l'avant et d'utiliser mon registre dans ceux-ci? Je ne sais pas assez comment les objets fonctionnent en PHP pour savoir s'il y aurait un gain de performance (moins d'utilisation de la mémoire, de l'utilisation du processeur, du temps de chargement). Donc, toute personne ayant de l'expérience dans ce domaine peut me dire s'il y aurait un gain en utilisant l'un ou l'autre, je suis au stade où je peux aller de l'autre sans affecter le temps de production ou quoi que ce soit. Je voudrais utiliser la meilleure méthode si je peux maintenant.

+0

tout à l'heure qui est basiquement la même http://stackoverflow.com/questions/1967363/registry-or-singleton – JasonDavis

+0

Prenez note si vous utilisez PHP4 ou PHP5 ... objets fonctionnent très différemment, et en PHP4, les mots clés comme 'static' ne sont pas supportés. Les chances sont que vous utilisez 5, mais si vous voulez entrer dans la POO pertinente, vous devez être sûr. –

Répondre

3

Cela dépend de votre application. Si vous avez toujours besoin de 3 classes sur 4, alors il serait plus idéal d'utiliser le registre que de gérer les 3 indépendamment seulement parce que vous n'avez pas besoin du quatrième. Charger les classes paresseusement serait une approche pour réduire l'empreinte de la mémoire, mais ensuite vous devez indiquer au registre quand créer les objets et ce n'est pas très différent de la manipulation des singletons. Vous pouvez également créer un constructeur à n paramètres ou utiliser un tableau pour indiquer au registre les classes à instancier pendant la construction. Puis instanciez votre registre en spécifiant les classes à instancier.

class Registry { 
    public $class1; 
    public $class2; 

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

} 

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

Vous voudriez évidemment que votre constructeur gère les paramètres zéro pour prendre en compte l'instanciation de toutes les classes par défaut.

+0

C'est une idée géniale, merci. Je devrais mentionner, même si 1 classe n'a besoin que de 1 à 2 des objets, il y a déjà une autre classe appelée sur la même page qui probablement aura également tous les 4 objets déjà injectés dedans. Je ne suis pas sûr de la façon dont les choses de la mémoire se retrouvent donc il peut être déjà chargé 1 fois. Je ne sais pas si la mémoire permettrait de stocker les objets plus d'une fois dans le bélier ou non. – JasonDavis

+0

Mon exemple de code suppose que vos classes conservent leur propre instance de votre registre. Cela signifierait beaucoup de mémoire en excès si vous avez plus d'une classe par page utilisant les mêmes objets de registre communs. Si vous utilisez une instance statique/globale, votre implémentation sera différente de mon exemple, mais cela pourrait toujours être fait. Cela signifierait également partager les mêmes objets en mémoire dans toutes les classes, ce qui serait beaucoup plus efficace. Pour que mon exemple fonctionne de cette façon, faites une fonction Registry :: initInstances() au lieu d'utiliser le constructeur. –

+0

Ok c'est ce que je pensais, je suppose que nous sommes sur la même page, un peu comme la méthode de dbemerlin ci-dessous. – JasonDavis

4

Vous pouvez implémenter vous avez vraiment besoin de chargement paresseux pour charger uniquement les objets:

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; 
    } 
} 

Le code pour enregistrer les paramètres de connexion de base est laissée comme exercice pour le lecteur.

+3

N'est-ce pas juste un singleton? – JasonDavis

+0

Je ne sais pas quoi d'autre peut être appelé un singleton –

+0

Ceci est le motif singleton pur, ce n'est pas vraiment un motif, mais plutôt un anti-pattern. –

1

C'est peut-être le modèle Singleton-Registry approprié. OFC, vous pouvez implémenter différentes choses, SplFixedArray, ArrayAccess interface, et d'autres. Aussi, il n'est pas mauvais d'ajouter la destruction et de détruire les objets internes pour éviter toute fuite. J'ai trouvé une question

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) 
Questions connexes