Designmuster korrigieren - Singleton in PHP

Ich habe kürzlich darüber geschrieben, wie man das Designmuster bricht - Singleton in PHP . Nachdem ich den Artikel geschrieben hatte, suchte ich nach einer neuen Version der Implementierung des Musters: Gibt es eine Möglichkeit, Singleton in PHP zu erstellen, ohne die Möglichkeit zu geben, neue Instanzen der Klasse mit Closure::bind() zu erstellen?


So beheben Sie Singleton in PHP


Ich habe mir viele verschiedene Optionen ausgedacht, aber auch Wege gefunden, um sie zu umgehen. Es schien mir, dass es nicht möglich sein würde, eine neue Implementierung zu erstellen, aber eine Idee kam auf und ich fing an, sie zu testen.


Hier in der Tat der Code und der Link zur Sandbox . Nehmen wir es auseinander:


 <?php final class Singleton { public static function getInstance() { static $instance; if (null === $instance) { $instance = new self(); } return $instance; } private function __construct() { static $hasInstance = false; if ($hasInstance) { \trigger_error('Class is already instantiated', \E_USER_ERROR); } $hasInstance = true; } private function __clone() { \trigger_error('Class could not be cloned', \E_USER_ERROR); } private function __wakeup() { \trigger_error('Class could not be deserialized', \E_USER_ERROR); } } $s1 = Singleton::getInstance(); \var_dump(\spl_object_id($s1)); $createNewInstance = function () { return new self(); }; $newInstanceClosure = Closure::bind($createNewInstance, $s1, Singleton::class); // Fatal error: Class is already instantiated $newInstanceClosure(); 

Wir übertragen die statische Variable $instance an die Methode getInstance() , sodass wir nicht mit den Operatoren self und static in der anonymen Funktion darauf zugreifen können.


Im Klassenkonstruktor fügen wir außerdem eine statische Variable hinzu, die einen booleschen Wert speichert. Beim Erstellen eines neuen Objekts überprüfen wir den Wert dieser Variablen: Wenn dort false gespeichert ist, setzen wir diese Variable auf true und das Objekt wird erfolgreich erstellt. Beim Versuch, ein neues Objekt zu erstellen, fällt der Code in if , da beim Erstellen des ersten Objekts true in die statische Variable $hasInstance , dann im if 'body, und wir verursachen einen Benutzerfehler, da die Textklasse Class is already instantiated .


In den magischen Methoden __clone() und __wakeup() verursachen wir auch Benutzerfehler mit den entsprechenden Nachrichten, um keine Objekte mit dem clone und dem Serialisierungsmechanismus in einer anonymen Funktion erstellen zu können.


Bei Bedarf können Sie Ausnahmen anstelle von Benutzerfehlern auslösen.


Somit ist es möglich, nur ein Singleton-Objekt der Klasse zu erstellen. Bisher habe ich keinen Weg gefunden, diese Implementierung des Musters zu brechen. Wenn also jemand dazu in der Lage ist, schreibe darüber im Kommentar :)


Vielen Dank für Ihre Aufmerksamkeit!

Source: https://habr.com/ru/post/de450626/


All Articles