إصلاح نمط التصميم - Singleton في PHP

كتبت مؤخرًا حول كيفية كسر نمط التصميم - Singleton في PHP . بعد كتابة المقالة ، كنت أبحث عن إصدار جديد من تنفيذ النموذج: هل هناك طريقة لإنشاء Singleton في PHP دون إعطاء الفرصة لإنشاء مثيلات جديدة من الفصل باستخدام Closure::bind() ؟


كيفية إصلاح سينجلتون في PHP


توصلت إلى العديد من الخيارات المختلفة ، لكنني وجدت أيضًا طرقًا للتغلب عليها. بدا لي بالفعل أنه لن يكون من الممكن إنشاء تطبيق جديد ، لكن الفكرة جاءت وبدأت في اختباره.


هنا ، في الواقع ، رمز وصلة إلى رمل . لنفصلها:


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

نقوم بنقل المتغير static $instance إلى أسلوب getInstance() حتى لا يمكننا الوصول إليه باستخدام العوامل self static في الوظيفة المجهولة.


في مُنشئ الفصل الدراسي ، نضيف أيضًا متغيرًا ثابتًا يخزن قيمة منطقية. عند إنشاء كائن جديد ، نتحقق من قيمة هذا المتغير: إذا تم تخزين false هناك ، فسنقوم بتعيين هذا المتغير على true ويتم إنشاء الكائن بنجاح. عند محاولة إنشاء كائن جديد ، $hasInstance الشفرة في if ، لأنه عند إنشاء الكائن الأول كتبنا true للمتغير الثابت $hasInstance ، ثم في $hasInstance ، $hasInstance في حدوث خطأ مستخدم في النص Class is already instantiated .


في الطرق السحرية __clone() و __wakeup() أيضًا في أخطاء المستخدم مع الرسائل المقابلة حتى لا نتمكن من إنشاء كائنات باستخدام عامل clone وآلية التسلسل في وظيفة مجهولة.


إذا رغبت في ذلك ، يمكنك رمي استثناءات بدلاً من أخطاء المستخدم.


وبالتالي ، من الممكن إنشاء كائن Singleton واحد فقط من الفصل الدراسي. حتى الآن ، لم أجد طريقة لكسر هذا التطبيق للنمط ، لذلك إذا كان بإمكان شخص ما فعل ذلك ، فاكتب عنه في التعليق :)


شكرا لاهتمامكم!

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


All Articles