Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

نمط 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");
}
challenge icon

التحدي

سهل

لنبنِ مدير إعدادات باستخدام نمط 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 المسترجع عبر المرجع الثاني

?>
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم PHP عبر الإنترنت