الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

Design Patterns: singleton

مغلق
بدأه hasan_aljudy في 3 نوفمبر 2005 · 2 رد · 1,988 مشاهدة · في المواضيع والدروس
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم

اقتداءا بموضوع أخي فيصل الردادي في منتدى الجافا, /index.php?showtopic=74039

نبدأ هذه السلسلة إن شاء الله.

أولا: ماذا تقصد بـ design pattern؟

العبارة تعني اشكال في تصميم اجزاء من البرامج تتكرر بكثرة. لتفهم المعنى اكثر, من الأفضل ان تنظر الى أمثلة لانواع مختلفة من الـ design patterns حتى تفهم الفكرة.

الـ pattern اللذي سنتناوله اليوم إن شاء الله هو الـ singleton

سيناريو المشكلة: صممنا برنامج معين, و البرنامج يحتوي على class أساسي في عمل البرنامج, و تبعا لطريقة عمل البرنامج, فإنه من غير المعقول وجود أكثر من نسخة واحدة من هذا الـ class في نفس الوقت, كما أننا نريد السماح بالوصول لهذا الكائن من أي مكان في البرنامج.

أمثلة على هذا: مثلا, كلاس اسمه application مهمته تمثيل البرنامج, او كلاس اسمه DataBase يمثل قاعدة البيانات, إذا كانت هناك قاعدة بيانات واحدة فقط! او مثلا, كائن اللاعب في لعبة يلعب فيها شخص واحد .. و هناك حالات كثيرة.

الحل:

اولا نريد ان نمنع أي شخص من إنشاء نسخة جديدة من الكلاس .. لعمل ذلك سوف نجعل الـ constructr نجعله private.

لنقم أولا بإنشاء الكلاس:

class Example
{
private:

public:
};

و نضع الـ constructor تحت الـ private

class Example
{
private:
    Example() //private, no one can istantiate this class!
    {
    }

public:

};

و لكن اذا لم يكن بإمكان احد ان ينشئ نسخة من هذا الكلاس, فما فائدته؟ لا بد لنا من طريقة بحيث نقوم بإنشائه مرة واحدة, و من ثم نمنع أي شخص من إنشاء نسخة جديدة.

لحسن الحظ ان الكلاس نفسه يستطيع إنشاء نفسه!

سنقوم بوضع function جديد داخل الكلاس, و لكنه سيكون static, و سيقوم بإنشاء نسخة من هذا الكائن, و حفظه في مؤشر, و سيكون ايضا static

class Example
{
private:
    Example() //private, no one can instantiate this class!
    {
    }

    static Example * instance; //the only instance that will exist
    static void createInstance()
    {
        instance = new Example();
    }

public:

};

و لكن كل شيء لا يزال private!! لا بد لنا من طريقة للسماح ببقية البرنامج بانشاء الكائن و استخدامه!

و لكن لحظة, إذا قمنا بإنشائه مرة .. ألن يكون بإمكاننا إنشائه عدة مرات؟

إذا, لتلافي هذا الأمر, سنقوم بوضع دالة تقوم بالتأكد فيما إذا كنا قد أنشأنا الكائن أم لا, فإذا كنا قد أنشئناه, فإنها لن تفعل شيئا, و إذا لم نكن قد أنشئناه بعد, ستقوم بإنشاء الكائن.

class Example
{
private:
    Example() //private, no one can istantiate this class!
    {
    }

    static Example * instance; //the only instance that will exist
    static void createInstance()
    {
        instance = new Example();
    }

public:
    static void instantiate()
    {
        if( instance == 0 )
        {
            createInstance();
        }
    }

};

و لكن لحظة, يجب اولا ان نقوم بعمل initialization للمؤشر instance بحيث يكون في البداية 0

لعمل ذلك يجب وضع هذا السطر خارج تعريف الكلاس:

Example * Example::instance = 0;

الان اكتمل المثال تقريبا, سنقوم فقط بتغيير بسيط للدالة instantiate بحيث تقوم بإعطائنا مؤشر للكائن, و ايضا سنغير اسمها لان مهمتها تغيرت:

class Example
{
private:
    Example() //private, no one can istantiate this class!
    {
    }

    static Example * instance; //the only instance that will exist
    static void createInstance()
    {
        instance = new Example();
    }

public:
    static Example * getInstance()
    {
        if( instance == 0 )
        {
            createInstance();
        }

        return instance; 
    }

};

Example * Example::instance = 0;

و الان لدينا كلاس لا يمكن الا انشاء نسخة واحدة منه, و يمكن لأي شخص في العالم الحصول على هذه النسخة عن طريق:

Example * e = Example::getInstance(); //get the singleton instance

و هذا مثال كامل, قابل للترجمة او عمل compile عليه, و قمت فيه بإضافة عضو صغير الى الكلاس للتجربة!

#include <iostream>
using namespace std;

class Example
{
    char * x;
private:
    Example() //private, no one can istantiate this class!
    {
        x = "hello world";
    }

    static Example * instance; //the only instance that will exist
    static void createInstance()
    {
        instance = new Example();
    }

public:
    static Example * getInstance()
    {
        if( instance == 0 )
        {
            createInstance();
        }

        return instance; 
    }

    void printMsg()
    {
        cout << x << endl;
    }

};

Example * Example::instance = 0;

int main()
{
    Example * e = Example::getInstance(); //get the singleton instance
    e->printMsg();

    return 0;
}
#2

أخي حسن الجـودي ..... كتبت درسين أنا في الـ Design Patterns كنت أريدها لمشروعي (والذي تركته طبعاً الآن) أي كتاب الإكسير الإصدار الثاني .. وهي عبارة عـن مبادئ الديزاين باترنس ومقدمـة بسيطة في الفاكتوريس وأيضاً في السينقلتون الذي وضعت درسـه عـنك ... فبعد إذنك هل بإمكاني وضعها هـنا

هذا الموضوع مغلق.

مواضيع مشابهة