جدول المحتويات:

كيفية عمل نمط تصميم Singleton في C ++: 9 خطوات
كيفية عمل نمط تصميم Singleton في C ++: 9 خطوات

فيديو: كيفية عمل نمط تصميم Singleton في C ++: 9 خطوات

فيديو: كيفية عمل نمط تصميم Singleton في C ++: 9 خطوات
فيديو: Фабричный шаблон - Майк Шах - CppCon 2021 2024, يونيو
Anonim
كيف تفعل نمط تصميم Singleton في C ++
كيف تفعل نمط تصميم Singleton في C ++

مقدمة:

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

نمط التصميم الفردي هو نمط تصميم يجب معرفته لأي مبرمج موجه للكائنات ومبرمجي برامج ومبرمجي ألعاب. يعد نمط التصميم الفردي أيضًا أحد أسهل أنماط تصميم الترميز الموجودة هناك. يمكن أن يساعدك تعلمه على تعلم أنماط تصميم أخرى أكثر صعوبة في المستقبل. يمكن أن يساعدك أيضًا في تبسيط كود البرنامج بطرق لم تعتقد أنها ممكنة.

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

سيستغرق هذا الدليل التعليمي في المتوسط حوالي 10-15 دقيقة.

متطلبات ماديه:

-جهاز كمبيوتر (يمكن أن يكون كمبيوتر شخصي أو Mac) قادر على تشغيل Visual Studios (أي إصدار)

-برنامج بسيط ، تم إنشاؤه في Visual Studios ، يمكنك اختباره الفردي الخاص بك

ملاحظة: يمكن عمل نمط التصميم الفردي على أي واجهة برمجة تطبيقات أخرى تدعم C ++ أو واجهة ترميز ، ولكن بالنسبة لمجموعة التعليمات هذه ، سنستخدم Visual Studios Enterprise Edition.

الخطوة 1: أنشئ فصلك الدراسي ، باستخدام ملف الرأس وملف CPP

أنشئ فصلك الدراسي ، باستخدام ملف الرأس وملف CPP
أنشئ فصلك الدراسي ، باستخدام ملف الرأس وملف CPP
أنشئ فصلك الدراسي ، باستخدام ملف الرأس وملف CPP
أنشئ فصلك الدراسي ، باستخدام ملف الرأس وملف CPP

لإنشاء هذين الملفين والفئة دفعة واحدة ، افتح مشروعك / برنامجك في Visual Studios ، وانتقل إلى مستكشف الحلول ، وانقر بزر الماوس الأيمن ، وسيظهر مربع بالقرب من مؤشر الماوس ، وابحث عن الخيار "إضافة" ، وحوم فوقه ، ويجب أن يظهر مربع آخر على اليمين. في هذا المربع ، تريد العثور على خيار "عنصر جديد.." ، انقر فوقه وستظهر نافذة تشبه الصورة 1.1 أدناه. في هذه النافذة ، تريد تحديد "فئة C ++" ثم النقر على "إضافة". سيؤدي هذا إلى فتح نافذة أخرى تشبه الصورة 1.2. في هذه النافذة ، تكتب اسم فصلك في حقل "Class Name" وستقوم Visual Studios تلقائيًا بتسمية الملف الفعلي بعد اسم الفصل. لغرض هذه التعليمات ، سنقوم بتسمية صفنا "EngineDebugSingleton" ، ولكن يمكن أن يكون أي اسم قائم على الحروف. يمكنك الآن الضغط على "موافق" والمتابعة إلى الخطوة 2.

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

الخطوة 2: اضبط المُنشئ على خاص

اضبط المُنشئ على خاص
اضبط المُنشئ على خاص

باستخدام ملف CPP وملف الرأس الذي تم إنشاؤه حديثًا ، إذا لم يتم فتحه تلقائيًا عند إنشائه ، فانتقل إلى مستكشف الحلول وانقر على "EngineDebugSingleton.h" وافتحه. سيتم الترحيب بك بعد ذلك بـ "EngineDebugSingleton ()" ، والمنشئ الافتراضي للفئة و "~ EngineDebugSingleton ()" مدمر الفئة. في هذه الخطوة ، سنرغب في ضبط المُنشئ على الخاص ، وهذا يعني أن هذه الوظيفة متاحة فقط للفئة وليس لأي شيء آخر. باستخدام هذا ، لن تكون قادرًا على عمل متغير أو تخصيص الفصل للذاكرة خارج الفصل ، فقط في ملف رأس الصفوف ووظائف الفئات الأخرى. يعد امتلاك المُنشئ خاصًا أمرًا أساسيًا لنمط التصميم وكيفية عمل المفردات. سوف نكتشف في الخطوات المستقبلية كيف يتم إنشاء مثيل مفرد والوصول إليه.

يجب أن يبدو الفصل الآن بهذا الشكل بعد نقل المُنشئ إلى خاص (انظر إلى الصورة المرتبطة)

الخطوة 3: اضبط التدمير على خاص

اضبط التدمير على خاص
اضبط التدمير على خاص

كما فعلنا مع المُنشئ في

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

يجب أن يبدو الفصل الآن بهذا الشكل بعد الانتهاء من هذه الخطوة. (انظر الصورة المرتبطة)

الخطوة 4: إنشاء متغير مؤشر ثابت في Singleton

إنشاء متغير مؤشر ثابت في المفرد
إنشاء متغير مؤشر ثابت في المفرد

في هذه الخطوة ، سننشئ ملف

متغير مؤشر ثابت من النوع "EngineDebugSingleton *". سيكون هذا هو المتغير الذي سيتم استخدامه لتخصيص المفرد الخاص بنا للذاكرة وسيشير إليه طوال الوقت الذي يتم فيه تخصيص مفردنا للذاكرة.

هذا ما يجب أن يبدو عليه ملف الرأس بعد إنشاء هذا المتغير

الخطوة 5: إنشاء دالة مثيل

إنشاء وظيفة المثيل
إنشاء وظيفة المثيل

نريد الآن أن نجعل مثالا

وظيفة. يجب أن تكون الوظيفة دالة ثابتة وستريد إرجاع مرجع إلى صفنا (“EngineDebugSingleton &”). أطلقنا على مثال وظيفتنا (). في الوظيفة نفسها ، سنرغب أولاً في اختبار ما إذا كان ptrInstance == nullptr (يمكن اختصاره إلى! ptrInstance) ، إذا كان nullptr ، فهذا يعني أنه لم يتم تخصيص المفرد وفي نطاق عبارة if ، تريد التخصيص بعمل ptrInstance = new EngineDebugSingleton (). هذا هو المكان الذي تخصص فيه المفرد للذاكرة. بعد الخروج من نطاق تعليمة if ، سنعيد ما يشير إليه ptrInstance ، والذي يُشار إليه بالصيغة “* ptrInstance”. سنستخدم هذه الوظيفة بكثافة عند إنشاء وظائفنا العامة الثابتة ، حتى نتمكن من التحقق لمعرفة ما إذا تم إنشاء المفرد وتخصيصه للذاكرة. في جوهرها ، هذه الوظيفة تجعلها بحيث يمكنك الحصول على تخصيص واحد فقط للفصل وليس أكثر.

هذا ما يجب أن يبدو عليه الفصل الدراسي الآن بعد إنشاء وظيفة Instance (). كما ترون ، كل ما فعلناه بقي في القسم الخاص بالصف ، وسيتغير هذا قليلاً في الخطوات القليلة التالية.

الخطوة 6: إنشاء وظائف عامة ثابتة

إنشاء وظائف عامة ثابتة
إنشاء وظائف عامة ثابتة
إنشاء وظائف عامة ثابتة
إنشاء وظائف عامة ثابتة
إنشاء وظائف عامة ثابتة
إنشاء وظائف عامة ثابتة

بعد أن تكون قد صنعت الوظيفة من

الخطوة 5 ، يمكنك البدء في إنشاء وظائف عامة ثابتة. يجب أن يكون لكل وظيفة عامة وظيفة خاصة تتماشى معها ، ولا يمكن أن يكون اسم هذه الوظيفة هو نفسه. لماذا تجعل الوظيفة ثابتة؟ نجعل الوظائف العامة ثابتة بحيث يمكن الوصول إليها بدون كائن فعلي. لذا بدلاً من القيام بشيء مثل "EngineDebugSingleObj-> SomeFunction ()" ، نقوم بعمل "EngineDebugSingleton:: Some Function ()". هذا يجعل من الممكن الوصول إلى المفرد بشكل أساسي في أي مكان في الكود ، شريطة أن # تضمين ملف الرأس في ملف المشروع المحدد الذي تعمل معه. باستخدام هذا ، يمكنك أيضًا إنشاء المفرد من خلال أي من وظائفه العامة.

لأغراضنا في هذه الخطوة ، أنشأنا وظيفتين عامتين فارغتين ، "add ()" و "طرح ()". في القسم الخاص ، لدينا وظيفتان إضافيتان ، "PrivAdd ()" و "PrivSubtract ()". أضفنا أيضًا متغيرًا int يسمى "NumberOfThings". سيذهب تعريف هذه الوظائف إلى ملف CPP لفصولنا. لجعل الوظيفة تدخل بسهولة إلى ملف CPP ، يمكنك تمييز الوظيفة التي يجب أن يكون تحتها خط أخضر ، ثم الضغط على "Left ALT + ENTER" ، ستمنحك خيار إنشاء التعريف في ملف CPP المرتبط بالفصول الدراسية. راجع الصورة 6.1 لمعرفة الشكل الذي يجب أن يبدو عليه ملف الرأس وبعد إنشاء جميع تعريفات الوظائف ، يجب أن تبدو CPP الخاصة بك مثل Photo 6.2 فيما عدا أن تعريفات الوظائف الخاصة بك لن تحتوي على أية تعليمات برمجية فيها.

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

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

الخطوة 7: إنشاء وظيفة الإنهاء

إنشاء وظيفة الإنهاء
إنشاء وظيفة الإنهاء
إنشاء وظيفة الإنهاء
إنشاء وظيفة الإنهاء

نظرًا لأنه لا يمكننا سوى إلغاء تخصيص مفردة من الذاكرة في صفنا ، يجب علينا إنشاء وظيفة عامة ثابتة. ستستدعي هذه الوظيفة الحذف على ptrInstance ، الذي يستدعي أداة تدمير الصنف ثم نرغب في إعادة تعيين ptrInstance إلى nullptr حتى يمكن تخصيصه مرة أخرى إذا لم ينتهي برنامجك. ستحتاج أيضًا إلى إنهاء Singletons الخاص بك لتنظيف أي ذاكرة مخصصة قمت بتخصيصها في أي متغيرات خاصة لـ Singleton.

الخطوة 8: ضبط PtrInstance على Nullptr

ضبط PtrInstance على Nullptr
ضبط PtrInstance على Nullptr

لإكمال ملفك الفردي ، تريد التوجه إلى ملف EngineDebugSingleton. CPP وفي أعلى ملف CPP ، في المثال الخاص بنا ، اكتب "EngineDebugSingleton * EngineDebugSingleton:: ptrInstance = nullptr."

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

الخطوة 9: الاختبار والاستنتاج

الاختبار والاستنتاج
الاختبار والاستنتاج

سنرغب الآن في اختبار ما إذا كان المفرد الخاص بنا للتأكد من أنه يعمل ، وهذا سيشملنا استدعاء الوظائف العامة كما هو موضح في الخطوة 6 وننصحك بإعداد نقاط توقف للتنقل عبر الكود الخاص بك ومعرفة أن المفرد يعمل كما هو موضح في الخطوة 6. يجب أن يكون. ستكون نقطة البداية في main.cpp الخاصة بمشروعنا ويبدو main.cpp لدينا الآن مثل الصورة أدناه.

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

يجب أن يبدو ملف الرأس النهائي الخاص بك مثل الصورة 7.1. يجب أن يبدو ملف CPP المرتبط بمفردك مثل Photo 6.2 مع إضافة ، في الجزء العلوي من الملف ، من الشفرة الموضحة في الخطوة 8. هذه التعليمات توفر لك بنية بسيطة لنمط تصميم Singleton.

نصيحة استكشاف الأخطاء وإصلاحها:

الحصول على أخطاء تتعلق بالذاكرة؟

تأكد من الرجوع إلى الخطوة 7 والخطوة 8 للتأكد من ضبط ptrInstance على nullptr.

حدوث حلقة لانهائية؟

تأكد من الوظائف العامة ، في تعريفاتها ، أنك تستدعي الوظيفة الخاصة ، وليس الوظيفة العامة نفسها.

الكائنات المخصصة داخل المفرد تسبب تسرب الذاكرة؟

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