نمط Singleton
جزء من قسم البرمجة كائنية التوجه في رحلة PHP على Coddy. الدرس 71 من 91.
يُعد نمط Singleton نمط تصميم إنشائيًا يضمن أن يكون للفئة مثيل واحد فقط طوال دورة حياة تطبيقك. كما يوفر نقطة وصول عامة إلى ذلك المثيل.
يكون هذا النمط مفيدًا عندما تحتاج إلى كائن واحد بالضبط لتنسيق الإجراءات عبر النظام، مثل اتصال بقاعدة بيانات، أو مدير إعدادات، أو مسجّل. قد يؤدي إنشاء مثيلات متعددة من هذه العناصر إلى هدر الموارد أو التسبب في سلوك غير متسق.
إليك كيفية تنفيذ Singleton في PHP:
<?php
class Database {
private static ?Database $instance = null;
private function __construct() {
// المُنشئ الخاص يمنع الإنشاء المباشر
}
public static function getInstance(): Database {
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function query(string $sql): string {
return "Executing: $sql";
}
}
$db1 = Database::getInstance();
$db2 = Database::getInstance();
echo $db1 === $db2 ? "Same instance" : "Different instances";
المخرجات:
Same instanceيعتمد النمط على ثلاثة عناصر أساسية: private constructor يمنع استخدام new مباشرةً، وخاصية ساكنة تحتفظ بـ instance الوحيدة، وmethod ساكنة تنشئ instance عند الاستدعاء الأول وتعيدها عند الاستدعاءات اللاحقة.
لجعل Singleton محكمًا تمامًا، ينبغي عليك أيضًا منع cloning وإلغاء التسلسل:
<?php
private function __clone() {}
public function __wakeup() {
throw new Exception("Cannot unserialize singleton");
}
التحدي
سهللنبنِ مدير إعدادات باستخدام نمط Singleton. في التطبيقات الحقيقية، تريد عادةً مصدرًا واحدًا للحقيقة لإعدادات التكوين: إذ قد يؤدي وجود كائنات تكوين متعددة إلى سلوك غير متسق عبر نظامك.
ستنظم شيفرتك عبر ملفين:
Config.php: أنشئ فئةConfigتطبق نمط Singleton. يجب أن يقوم مدير التكوين لديك بما يلي:- تخزين الإعدادات في خاصية array private
- امتلاك constructor private يقوم بتهيئة array الإعدادات كـ empty
- توفير الطريقة static
getInstance()التي returns الـ instance الوحيد - prevent cloning بجعل
__clone()private - تضمين الطريقة
set(string $key, string $value): voidلتخزين إعداد - تضمين الطريقة
get(string $key): ?stringالتي returns القيمة الخاصة بـ key، أوnullإذا لم يكن key موجودًا - تضمين الطريقة
getAll(): arrayالتي returns جميع الإعدادات
main.php: ضمّن ملف Config. ستتلقى مدخلين: key وvalue.احصل على instance الخاص بـ Config واضبط إعدادًا افتراضيًا باستخدام key
"app_name"وvalue"MyApp".احصل على reference ثانية إلى instance الخاص بـ Config (باستخدام
getInstance()مرة أخرى) واستخدمها لضبط إعداد آخر باستخدام key وvalue القادمين من المدخلات.أخيرًا، تحقّق من أن Singleton يعمل بشكل صحيح:
- اطبع
"Same instance: true"أو"Same instance: false"بناءً على ما إذا كان كلا المرجعين يشيران إلى الكائن نفسه (استخدم===للمقارنة) - اطبع
"Settings count: [count]"لإظهار العدد الإجمالي للإعدادات المخزنة (استخدمcount()على نتيجةgetAll()) - اطبع
"App name: [value]"لإظهار إعداد app_name retrieved عبر reference الثانية
- اطبع
يوضح هذا التحدي الفائدة الأساسية لنمط Singleton: بغض النظر عن عدد مرات استدعائك لـ getInstance()، ستحصل always على الكائن نفسه، مما يضمن مشاركة جميع أجزاء تطبيقك لحالة التكوين نفسها.
جرّب بنفسك
<?php
require_once 'Config.php';
// اقرأ الإدخال
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));
// TODO: احصل على مثيل Config وعيّن "app_name" إلى "MyApp"
// TODO: احصل على مرجع ثانٍ لـ Config باستخدام getInstance() مرة أخرى
// TODO: استخدم المرجع الثاني لتعيين الإعداد باستخدام $key و $value من الإدخال
// TODO: تحقق من أن Singleton يعمل:
// - Print "Same instance: true" or "Same instance: false" based on === comparison
// - Print "Settings count: [count]" showing total settings
// - اطبع "App name: [value]" موضحًا app_name المسترجع عبر المرجع الثاني
?>يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1أساسيات OOP
الملفات الخارجيةمقدمة في OOPClasses مقابل Objectsالكلمة المفتاحية $thisالـ Methodsالـ Propertiesالمنشئ (__construct)الهادم (__destruct)مراجعة - آلة حاسبة بسيطة4الوراثة
الوراثة الأساسيةالكلمة المفتاحية parent::إعادة تعريف الدوال (Method Overriding)الكلمة المفتاحية finalالأصناف المجردة (Abstract Classes)مراجعة - هيكلية الموظفين7التغليف (Encapsulation)
العام، المحمي، الخاص (Public, Protected, Private)نظرة متعمقة على معدلات الوصولدوال Getters و Settersإخفاء المعلوماتميزة Constructor Promotion (8.0)مراجعة - نظام سجلات الطلاب10مفاهيم البرمجة كائنية التوجه المتقدمة
التركيب مقابل الوراثةحقن التبعيةالأصناف المجهولةالتعدادات (PHP 8.1)الألياف (PHP 8.1)تعمق في استنساخ الكائناتالمولدات والمكررات13أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط طريقة القالبنمط الحالةنمط التركيبنمط المستودع2مساحات الأسماء والتحميل التلقائي
مقدمة إلى مساحات الأسماءالكلمة المفتاحية useمعيار التحميل التلقائي PSR-4أداة التحميل التلقائي Composerملخص - مشروع منظم5الواجهات والعقود
مقدمة إلى الواجهاتتنفيذ الواجهاتتنفيذ واجهات متعددةالواجهة مقابل الـ Abstract Classالـ Type Hinting مع الواجهاتملخص - حاسبة الأشكال8الميثودات السحرية (Magic Methods)
مقدمة في الميثودات السحرية__toString و __debugInfo__get, __set, __isset, __unset__call و __callStatic__clone واستنساخ الكائنات__serialize و __unserializeمراجعة - Custom Collection3خصائص الكلاس
خصائص الـ Instance مقابل الخصائص الساكنة (Static)الثوابت في الكلاساتالدوال والخصائص الساكنة (Static)الخصائص الخاصة (Private) والمحمية (Protected)خصائص للقراءة فقط (Readonly) في PHP 8.1مراجعة - مدير الحساب البنكي6تعدد الأشكال (Polymorphism)
مراجعة إعادة تعريف الدوال (Method Overriding)تعدد الأشكال عبر الـ Interfacesتلميح النوع (Type Hinting) وأنواع الاتحاد (Union Types)الربط الاستاتيكي المتأخر (Late Static Binding)ملخص - معالج الدفع (Payment Processor)تدرّب بنفسك: مترجم PHP عبر الإنترنت