Perbaiki pola desain - Singleton dalam PHP

Baru-baru ini saya menulis tentang cara memecahkan pola desain - Singleton dalam PHP . Setelah menulis artikel, saya mencari versi baru dari implementasi pola: apakah ada cara untuk membuat Singleton dalam PHP tanpa memberikan kesempatan untuk membuat instance baru dari kelas menggunakan Closure::bind() ?


Bagaimana cara memperbaiki Singleton di PHP


Saya datang dengan banyak pilihan berbeda, tetapi juga menemukan cara untuk mengatasinya. Sepertinya saya sudah tidak mungkin membuat implementasi baru, tetapi sebuah ide datang dan saya mulai mengujinya.


Di sini, sebenarnya, kode dan tautan ke kotak pasir . Mari kita pisahkan:


 <?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(); 

kami mentransfer variabel statis $instance ke metode getInstance() sehingga kami tidak dapat mengaksesnya menggunakan operator static dan self dalam fungsi anonim.


Di konstruktor kelas, kami juga menambahkan variabel statis yang menyimpan nilai Boolean. Saat membuat objek baru, kami memeriksa nilai variabel ini: jika false disimpan di sana, kami menetapkan variabel ini ke true dan objek berhasil dibuat. Ketika mencoba membuat objek baru, kode akan jatuh ke if , karena ketika membuat objek pertama kita menulis true ke variabel statis $hasInstance , kemudian di tubuh if ', dan kita akan menyebabkan kesalahan pengguna dengan teks Class is already instantiated .


Dalam metode ajaib __clone() dan __wakeup() kami juga menyebabkan kesalahan pengguna dengan pesan yang sesuai agar tidak dapat membuat objek menggunakan operator clone dan mekanisme serialisasi dalam fungsi anonim.


Jika diinginkan, Anda dapat membuang pengecualian alih-alih kesalahan pengguna.


Dengan demikian, dimungkinkan untuk membuat hanya satu objek Singleton dari kelas. Sejauh ini, saya belum menemukan cara untuk mematahkan implementasi pola ini, jadi jika seseorang dapat melakukannya, tulis tentang itu di komentar :)


Terima kasih atas perhatian anda!

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


All Articles