2010-01-20 8 views
10

Ich arbeite jetzt mit PHP Klassen und Objekten. In dieser Frage sind die Namen der Felder und Methoden so zusammengesetzt, dass Sie eine Vorstellung davon bekommen, wovon ich rede.Registrierung oder Singleton-Muster in PHP?

Es bezieht sich auf die Verwendung der Singleton- und Registrierungsentwurfsmuster.

Nun sagen wir, ich brauche Zugriff auf ein Datenbank-Objekt, Cache-Objekt, Core Settings-Objekt, Session-Objekt in fast jeder anderen Klasse, ich muss Zugriff auf diese haben. SO würde ich eine Registrierung verwenden, um alle 4 dieser Objekte in 1 Registrierungsklassenobjekt zu speichern. Ich könnte dann einfach mein 1 Objekt in ein anderes Objekt einbringen, das auf diese zugreifen muss. Das hört sich großartig an, aber was ist, wenn ich einige Klassen habe, die nicht alle 4 dieser Objekte benötigen? Was, wenn ich nur auf das Database-Objekt oder das Session-Objekt in einigen meiner anderen Klassen zugreifen muss? Für die Leistung wäre es am besten, nur ein Singleton innerhalb dieser anderen Objekte zu verwenden, oder wäre es das Gleiche, weiter zu gehen und meine Registrierung in diesen zu verwenden?

Ich weiß nicht gut genug, wie die Objekte in PHP arbeiten, um zu wissen, ob es irgendeine Art von Leistungsgewinn (weniger Speicherauslastung, CPU-Auslastung, Ladezeit) geben würde.

Also jemand mit Erfahrung in diesem vielleicht kann mir sagen, ob es einen Gewinn mit der einen oder anderen, ich bin in dem Stadium, wo ich gehen kann, ohne es die Produktionszeit oder etwas beeinflussen. Ich würde gerne die beste Methode verwenden, wenn ich es jetzt kann.

+0

Ich fand tatsächlich eine Frage ist jetzt nur, dass im Grunde das gleiche ist http://stackoverflow.com/questions/1967363/registry-or-singleton – JasonDavis

+0

zur Kenntnis nehmen, wenn Sie PHP4 oder PHP5 verwenden ... Objekte arbeiten sehr unterschiedlich, und in PHP4 werden Schlüsselwörter wie 'statisch' nicht unterstützt. Wahrscheinlich verwenden Sie 5, aber wenn Sie in relevante OOP gelangen wollen, müssen Sie sicher sein. –

Antwort

3

Das hängt von Ihrer Anwendung ab. Wenn Sie noch 3 der 4 Klassen benötigen, dann wäre es ideal, die Registrierung zu verwenden, als die 3 unabhängig zu behandeln, nur weil Sie die vierte nicht benötigen. Das faule Laden der Klassen wäre ein Ansatz, um den Speicherbedarf zu reduzieren, aber dann müssen Sie die Registrierung anweisen, wann die Objekte erstellt werden, und das ist nicht viel anders als die Behandlung von Singletons. Alternativ können Sie einen N-Parameter-Konstruktor erstellen oder ein Array verwenden, um Ihre Registrierung anzuweisen, welche Klassen während der Konstruktion instanziiert werden.

class Registry { 
    public $class1; 
    public $class2; 

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

} 

Dann instanziieren Sie Ihre Registrierung, indem Sie angeben, welche Klassen instanziiert werden sollen.

Sie möchten offensichtlich, dass Ihr Konstruktor Nullparameter behandelt, um standardmäßig alle Klassen instanziieren zu können.

+0

Das ist eine coole Idee, danke. Ich sollte erwähnen, dass, selbst wenn 1 Klasse nur 1-2 der Objekte benötigt, bereits eine andere Klasse auf der gleichen Seite aufgerufen wird, die höchstwahrscheinlich auch alle 4 Objekte enthalten wird. Ich bin mir nicht sicher, wie das Speicherkram verschleiert wird, also könnte es schon 1 mal geladen sein. Ich weiß nicht, ob der Speicher die Objekte mehr als einmal im RAM speichern würde oder nicht. – JasonDavis

+0

In meinem Codebeispiel wird davon ausgegangen, dass Ihre Klassen an ihrer eigenen Instanz Ihrer Registrierung festhalten. Dies würde viel überschüssigen Speicher bedeuten, wenn Sie mehr als eine Klasse pro Seite verwenden, die dieselben allgemeinen Registrierungsobjekte verwenden. Wenn Sie eine statische/globale Instanz verwenden, würde sich Ihre Implementierung von meinem Beispiel unterscheiden, könnte aber trotzdem durchgeführt werden. Dies würde auch bedeuten, dieselben Objekte im Speicher über alle Klassen hinweg zu teilen, was sehr viel effizienter wäre. Um mein Beispiel auf diese Weise zu erhalten, erstellen Sie eine Registry :: initInstances() -Funktion, anstatt den Konstruktor zu verwenden. –

+0

Ok, das ist, was ich dachte, schätze, wir sind auf der gleichen Seite, ähnlich wie die Methode von Dbemerlin unten. – JasonDavis

4

können Sie verzögertes Laden implementieren, um nur die Objekte laden Sie wirklich brauchen:

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

Der Code der Datenbank-Verbindungsparameter registrieren als Übung überlassen dem Leser.

+3

Ist das nicht nur ein Singleton? – JasonDavis

+0

Ich weiß nicht, was man sonst noch Singleton nennen könnte –

+0

Dies ist das reine Singleton-Muster, das ist nicht wirklich Muster, sondern eher Anti-Pattern. –

1

Vielleicht ist dies das richtige Singleton-Registry-Muster. OFC, können Sie verschiedene Dinge, SplFixedArray, ArrayAccess-Schnittstelle und andere implementieren. Es ist auch nicht schlecht, die inneren Objekte zu zerstören und zu zerstören, um sicherzustellen, dass kein Leck möglich ist.

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) 
Verwandte Themen