تركيزك على استخدام نمط البرمجة Singleton يدل على الرغبة في ضمان وجود مثيل واحد فقط من الكائنات التي تستخدم هذا النمط. إلا أن الشيفرة المعروضة تحتاج إلى بعض التعديلات لتكون مثالية.
أولاً وقبل كل شيء، دعوني أوضح كيف يعمل هذا النمط في الشيفرة التي قدمتها.
عندما تنشئ مثيلًا من الفئة singleton
، يتم تعيين العنوان الذي يشير إليه ms_singleton
ليشير إلى هذا المثيل المنشأ حديثًا. وعندما يتم إنشاء مثيل آخر، فإن هذا الشرط assert(!ms_singleton);
يتحقق، مما يضمن أن لا يتم إنشاء مثيل آخر.
من الناحية النظرية، هذا يعمل. ولكن هناك بعض المشاكل البسيطة في الشيفرة:
-
عدم تهيئة المؤشر الثابت: في بعض الحالات، قد تكون هناك مشكلة في تهيئة
ms_singleton
لقيمة افتراضية. يجب عليك ضمان تهيئتها بقيمة افتراضية غير معروفة، مثلnullptr
. -
إمكانية النسخ: يمكن نسخ
singleton
عن طريق الخطأ، وهو ما يمكن أن يؤدي إلى وجود مثيلات متعددة منه. يمكن حل هذه المشكلة ببساطة من خلال حذف المشيئة المنشأة والمتطورة وبدلاً من ذلك إنشاء المثيل بشكل صريح باستخدام دالةinstance()
. -
التدمير الآمن: في بعض الحالات، قد يكون هناك مشكلة في التأكد من أنه تم تدمير المثيل بشكل صحيح. يمكن تحسين هذا من خلال استخدام الحد الأدنى من الكود في الدالة المدمجة.
-
التعامل مع السلالة: يمكن أن يكون من الصعب فهم كيفية التعامل مع السلالة عند استخدام
singleton
كما هو موضح في الشيفرة.
إليك الشيفرة المحسنة:
cpp#include
#include
template <typename T> class Singleton
{
public:
static T& instance()
{
static T instance;
return instance;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
protected:
Singleton() {}
virtual ~Singleton() {}
};
class Test1: public Singleton
{
friend class Singleton; // Allow Singleton to access Test1's constructor
private:
Test1() {}
};
int main()
{
Test1& obj1 = Test1::instance();
Test1& obj2 = Test1::instance();
assert(&obj1 == &obj2); // Ensure only one instance exists
return 0;
}
تم تحسين هذه الشيفرة عن طريق:
- استخدام متغير ثابت محلي داخل الدالة
instance()
لضمان وجود مثيل واحد فقط من الفئة. - حذف إمكانية النسخ عن طريق حذف المشيئات المنشأة والمتطورة.
- تقليل الكود في الدالة المدمجة.
- تجنب التعامل مع السلالة في الفئة
Test1
.
باستخدام هذه الشيفرة المحسنة، يمكنك الآن ضمان وجود مثيل واحد فقط من Test1
وأي فئة أخرى تستخدم نمط البرمجة Singleton.
المزيد من المعلومات
بالطبع، إليك المقال المكتمل:
تحسين استخدام نمط البرمجة Singleton في C++
عند تصميم برنامج يستخدم العديد من الكائنات، يمكن أن تحدث مشاكل عند إنشاء مثيلات متعددة من نفس الفئة. لحل هذه المشكلة، يمكن استخدام نمط البرمجة Singleton الذي يهدف إلى ضمان وجود مثيل واحد فقط من الفئة في كل مرة يتم فيها استدعاءها.
في هذا المقال، قمت بتقديم تحسينات على شيفرة Singleton الأساسية لتحسين أدائها وتجنب بعض المشاكل الشائعة. دعونا نلقي نظرة على التحسينات التي قمت بها:
1. استخدام متغير ثابت محلي داخل الدالة instance()
باستخدام متغير ثابت محلي داخل الدالة instance()
، يمكننا ضمان أنه سيتم إنشاء مثيل واحد فقط من الفئة. يتم تهيئة هذا المتغير فقط عندما يتم استدعاء الدالة instance()
لأول مرة، ويتم إعادة استخدامه في كل استدعاء لاحق.
2. حذف إمكانية النسخ
بحذف المشيئات المنشأة والمتطورة، يمكننا منع إنشاء مثيلات إضافية من الفئة. هذا يحمينا من النسخ غير المقصود ويضمن وجود مثيل واحد فقط من الفئة.
3. تقليل الكود في الدالة المدمجة
بتقليل الكود في الدالة المدمجة، يمكننا تبسيط الشيفرة وجعلها أكثر فهمًا وسهولة للصيانة. تم تحقيق هذا عن طريق إزالة الشروط غير الضرورية والتحقق من الصحة.
4. تجنب التعامل مع السلالة في الفئة
بتجنب التعامل المباشر مع السلالة في الفئة، يمكننا تبسيط هيكل الفئة وتجنب الالتباس. يمكن لهذا أن يسهل فهم كيفية استخدام الفئة ويقلل من الأخطاء المحتملة.
باستخدام الشيفرة المحسنة، يمكنك الآن ضمان وجود مثيل واحد فقط من الفئة في كل مرة يتم فيها استدعاءها. هذا يسهل تصميم البرنامج ويجعله أكثر استقرارًا وصيانةً.
في النهاية، يمكن استخدام نمط البرمجة Singleton بشكل فعال لتجنب مشاكل إنشاء مثيلات متعددة في برنامجك. باستخدام التحسينات المقدمة، يمكنك ضمان أن تكون الشيفرة نظيفة ومنظمة، وأن تعمل بشكل مثالي في كل الظروف.