كيفية إنشاء Singleton في C++

Kyfyt Ansha Singleton Fy C



في لغة C++، يعتبر المفرد هو مبدأ التصميم الذي يضمن وجود مثيل منفرد للفئة في جميع أنحاء البرنامج ويوفر نقطة وصول عامة إلى هذا المثيل المعين.

يتم استخدام النمط المفرد بشكل شائع عندما تحتاج إلى مورد واحد مشترك يمكن الوصول إليه عالميًا مثل اتصال قاعدة البيانات أو المُسجل أو مدير التكوين. من خلال فرض مثيل واحد، فإنه يسمح لأجزاء متعددة من البرنامج بالوصول إلى نفس الكائن وتعديله، مما يعزز اتساق البيانات ويقلل الحاجة إلى المتغيرات العامة. يمكن استخدام Singleton كمخزن مؤقت للكائنات حيث يتم تخزين الكائنات المستخدمة بشكل متكرر أو باهظة الثمن عند إنشائها وإعادة استخدامها في جميع أنحاء التطبيق. يساعد هذا الأسلوب على تحسين الأداء عن طريق تجنب إنشاء كائنات متكررة وتهيئتها.

في هذه المقالة، سنشرح إنشاء نغمة مفردة ونعرض مثالاً لتصميم نغمة مفردة في برنامج C++.







المثال 1: إنشاء مفردة بسيطة باستخدام التهيئة السريعة

إن المفردة البسيطة ذات التهيئة المبكرة هي نمط تصميم يضمن إنشاء مثيل واحد فقط للفئة، ويتم إنشاؤه بفارغ الصبر أثناء التهيئة الثابتة.



سنعرض مقتطف الكود الأساسي لإنشاء مفردة بسيطة مع تهيئة حريصة. لنبدأ بالبرنامج:



#تشمل

فئة سينجلتون {
خاص :
ثابتة سينجلتون * مثال ;
سينجلتون ( ) { }
عام :
ثابتة سينجلتون * getInstance ( ) {
يعود مثال ;
}
} ;


سينجلتون * سينجلتون :: مثال = سينجلتون جديد ( ) ;

كثافة العمليات رئيسي ( ) {

سينجلتون * SingletonInstance1 = سينجلتون :: getInstance ( ) ;

سينجلتون * SingletonInstance2 = سينجلتون :: getInstance ( ) ;

الأمراض المنقولة جنسيا :: cout << 'المثيل المفرد 1:' << SingletonInstance1 << الأمراض المنقولة جنسيا :: endl ;

الأمراض المنقولة جنسيا :: cout << 'المثيل المفرد 2:' << SingletonInstance2 << الأمراض المنقولة جنسيا :: endl ;

يعود 0 ;

}

يتضمن الكود رأس الذي يوفر وظيفة العمل مع تدفقات الإدخال والإخراج مثل 'std::cout'.





بعد تضمين ملف الرأس، نحدد فئة 'Singleton' التي تمثل تنفيذ النمط المفرد. يحتوي على مُنشئ خاص ومتغير عضو ثابت خاص يسمى 'المثيل'.

بعد ذلك، يتم تنفيذ وظيفة getInstance() كوظيفة عضو ثابتة عامة لفئة 'Singleton'. تقوم بإرجاع مثيل المفردة المخزنة في مثيل متغير العضو الثابت. يتم تعريف مثيل متغير العضو الثابت وتهيئته خارج الفصل باستخدام 'Singleton* Singleton::instance = new Singleton();'. يقوم هذا الخط بتهيئة مثيل فئة 'Singleton' بفارغ الصبر أثناء التهيئة الثابتة.



في الدالة main()، نعلن عن مؤشرين، 'singletonInstance1' و'singletonInstance2'، ونقوم بتعيين القيمة التي يتم إرجاعها عن طريق استدعاء Singleton::getInstance(). نظرًا لتهيئة المثيل بفارغ الصبر، يشير كلا المؤشرين إلى نفس المثيل. تقوم عبارات 'std::cout' بطباعة عناوين الذاكرة الخاصة بـ 'singletonInstance1' و'singletonInstance2' إلى وحدة التحكم باستخدام عامل التشغيل '<<' و'std::endl'.

ينتهي الرمز بـ 'إرجاع 0' مما يشير إلى نجاح تنفيذ البرنامج.

عندما تقوم بتشغيل هذا الكود، يكون الإخراج كالتالي:

يعرض الإخراج عناوين الذاكرة لـ 'singletonInstance1' و'singletonInstance2'. نظرًا لأنه تم تعيين كلا المؤشرين بنفس المثيل الذي تم الحصول عليه من Singleton::getInstance()، فإن لهما نفس عنوان الذاكرة. يوضح هذا كيف يضمن النمط المفرد وجود مثيل واحد للفئة وأن الاستدعاءات المستقبلية لـ getInstance() تؤدي دائمًا إلى نفس المثيل.

المثال 2: تنفيذ النمط المفرد مع التهيئة البطيئة

يشرح هذا العرض التوضيحي تنفيذ النمط المفرد مع التهيئة البطيئة ويوضح استخدامه في الدالة main(). يتم توفير الشرح خطوة بخطوة لمقتطف الكود بعد هذا البرنامج:

#تشمل

فئة سينجلتون {

خاص :

ثابتة سينجلتون * مثال ;

سينجلتون ( ) {

الأمراض المنقولة جنسيا :: cout << 'تم إنشاء مثيل Singleton.' << الأمراض المنقولة جنسيا :: endl ;

}

عام :

ثابتة سينجلتون * getInstance ( ) {

لو ( مثال == nullptr ) {

مثال = سينجلتون جديد ( ) ;

}

يعود مثال ;

}

فارغ اظهر الرسالة ( ) {

الأمراض المنقولة جنسيا :: cout << 'مرحبا من سينجلتون!' << الأمراض المنقولة جنسيا :: endl ;

}

~ سينجلتون ( ) {

الأمراض المنقولة جنسيا :: cout << 'تم تدمير مثيل Singleton.' << الأمراض المنقولة جنسيا :: endl ;

}

} ;

سينجلتون * سينجلتون :: مثال = nullptr ;

كثافة العمليات رئيسي ( ) {

سينجلتون * SingletonInstance1 = سينجلتون :: getInstance ( ) ;

SingletonInstance1 -> اظهر الرسالة ( ) ;

سينجلتون * SingletonInstance2 = سينجلتون :: getInstance ( ) ;

SingletonInstance2 -> اظهر الرسالة ( ) ;

يعود 0 ;

}

يبدأ البرنامج بإضافة ملف الرأس لتنفيذ مهام الإدخال/الإخراج. ثم نعلن ونحدد فئة 'Singleton'. يتم الاحتفاظ بالمثيل الوحيد للفئة داخل متغير العضو الثابت الخاص المسمى 'المثيل'.

عندما يتم استدعاء مُنشئ فئة 'Singleton'، فإنه يقوم بإنشاء مثيل لفئة 'Singleton'. يقوم بإخراج رسالة 'تم إنشاء مثيل Singleton' إلى وحدة التحكم باستخدام 'std::cout << … << std::endl;'. لا يحتوي المنشئ على أي معلمات لأنه مُنشئ افتراضي. يتم تعريفه على أنه Singleton() بدون أية وسائط. نعلنها على أنها خاصة مما يعني أنه لا يمكن استدعاؤها إلا من داخل الفصل. يمنع هذا إنشاء مثيل مباشر لفئة 'Singleton' ويضمن أن الطريقة الوحيدة للحصول على مثيل هي من خلال وظيفة getInstance().

تم تعريف طريقة getInstance() الخاصة بالفئة 'Singleton' كوظيفة عضو ثابتة عامة. إنه دور إنشاء ومنح إمكانية الوصول إلى المثيل المفرد. داخل getInstance()، يتحقق مما إذا كان المثيل 'nullptr'. إذا كان الأمر كذلك، فهذا يعني أن المثيل غير موجود بالفعل، فإنه يستخدم المُنشئ الخاص لإنشاء كائن جديد من فئة 'Singleton'.

وظيفة showMessage() هي وظيفة عضو بسيطة تعرض رسالة 'Hello from Singleton!' رسالة. يتم تعريف المدمر للمفردة. يتم استدعاؤه ضمنيًا عندما ينتهي البرنامج ويطبع 'تم تدمير مثيل Singleton'. رسالة تشير إلى تدمير المثيل المفرد. يتم تعريف مثيل متغير العضو الثابت في البداية باسم 'nullptr'.

يبدأ int main() تعريف الوظيفة main(). بعد ذلك، 'Singleton* SingletonInstance1 = Singleton::getInstance();' يستدعي الدالة getInstance()‎ لفئة 'Singleton' للحصول على مؤشر لمثيل المفرد. يقوم بتعيين هذا المؤشر للمتغير 'singletonInstance1'.

بعد ذلك، سيتم عرض 'singletonInstance1->showMessage();' يستخدم عامل السهم (->) لاستدعاء وظيفة showMessage() على مؤشر 'singletonInstance1'. تعرض هذه الوظيفة الرسالة المحددة فيها إلى وحدة التحكم. بعد ذلك، 'Singleton* SingletonInstance2 = Singleton::getInstance();' يستدعي الدالة getInstance() مرة أخرى، ويحصل على مؤشر آخر للمثيل المفرد. هذه المرة، يقوم بتعيين المؤشر للمتغير 'singletonInstance2'. 'singletonInstance2->showMessage();' يستدعي الدالة showMessage() على مؤشر 'singletonInstance2'. تعرض هذه الوظيفة رسالة 'Hello from Singleton!' رسالة مرة أخرى إلى وحدة التحكم.

وأخيرا، 'العودة 0؛' يشير إلى نهاية الدالة main()، ويقوم البرنامج بإرجاع القيمة 0 التي تشير إلى تنفيذ البرنامج بنجاح.

فيما يلي مخرجات مقتطف الشفرة الموضح مسبقًا:

تؤكد هذه النتيجة أن فئة 'Singleton' تضمن إنشاء مثيل واحد فقط وأن الاستدعاءات الإضافية للدالة getInstance() تؤدي بشكل موثوق إلى نفس المثيل.

خاتمة

يعد إنشاء مفردة في C++ مفهومًا مفيدًا للغاية. في هذا المنشور، قمنا في البداية بتغطية قسم المقدمة للمفردة. علاوة على ذلك، تم إنتاج مثالين لتنفيذ المفردة في لغة C++. يوضح الرسم التوضيحي الأول تنفيذ التهيئة المفردة المتلهفة. بينما يتم توفير تنفيذ التهيئة البطيئة للنمط المفرد في المثال الثاني من هذه المقالة. علاوة على ذلك، يتم أيضًا عرض لقطات من المخرجات المنتجة للبرامج المقابلة.