المحتوى:
- أنماط التصميم الإبداعية “Creational patterns”
- ما هو نمط التصميم الإبداعي” Singleton design pattern”
- مشكلة يمكن حلها باستخدام نمط التصميم” Singleton design pattern”
- حل المشكلة باستخدام نمط التصميم” Singleton design pattern”
- بناء نمط التصميم الإبداعي” Singleton design pattern”
- تمثيل نمط التصميم ” Singleton design pattern” بشكل كود
- قابلية نمط التصميم ” Singleton design pattern” للتطبيق
- كيفية تنفيذ نمط التصميم ” Singleton design pattern”
- إيجابيات وسلبيات نمط التصميم ” Singleton design pattern “
- علاقات نمط التصميم ” Singleton design pattern ” مع الأنماط الأخرى
- الخاتمة
- المراجع
- أنماط التصميم الإبداعية “Creational patterns“.
الأنماط الإبداعية هي فئة من أنماط التصميم في هندسة البرمجيات التي تتعامل مع آليات إنشاء الكائنات، ومحاولة إنشاء الكائنات بطريقة مناسبة للموقف. تهدف الأنماط الإبداعية إلى توفير المرونة في عملية إنشاء الكائنات، مما يسمح للنظام بأن يكون مستقلاً عن كيفية إنشاء الكائنات وتكوينها وتمثيلها.
توفر أنماط التصميم الإبداعي آليات مختلفة لإنشاء الكائنات، مما يزيد من المرونة وإعادة استخدام التعليمات البرمجية الموجودة.
تتضمن بعض الأنماط الإبداعية شائعة الاستخدام ما يلي: Factory Method: تحدد واجهة لإنشاء كائن، ولكنها تسمح للفئات الفرعية بتغيير نوع الكائنات التي سيتم إنشاؤها.
Abstract Factory: يوفر واجهة لإنشاء عائلات من الكائنات المرتبطة أو التابعة دون تحديد فئاتها المحددة.
Builder: يفصل بناء كائن معقد عن تمثيله، مما يسمح لنفس عملية البناء بإنشاء تمثيلات مختلفة.
Prototype: ينشئ كائنات جديدة عن طريق نسخ كائن موجود، يُعرف بالنموذج الأولي، من خلال الاستنساخ.
وسنتحدث في هذه المقالة عن “Singleton Design Pattern”
وقد تحدثنا في المقالة السابقة عن ثاني نمط تصميم إبداعي وهو ” Prototype pattern“
فالنموذج الأولي هو نمط تصميم إبداعي يتيح لنا نسخ الكائنات الموجودة دون جعل التعليمات البرمجية الخاصة بنا تعتمد على فئاتها.
وسنكمل بالتحدث عن تتمة أنواع التصميم الإبداعي وسنبدأ بال “Singleton pattern“.
- ما هو نمط التصميم الإبداعي” Singleton pattern”.
في هندسة البرمجيات، Singleton هو نمط تصميم إبداعي يستخدم للتأكد من أن الفصل يحتوي على مثيل واحد فقط ويوفر نقطة وصول عالمية إلى هذا المثيل. يُستخدم هذا النمط بشكل شائع عندما نريد تقييد إنشاء فئة ما على كائن واحد، والذي يمكن أن يكون مفيدًا لمهام مثل إدارة الموارد التي يجب مشاركتها عبر التطبيق، مثل اتصالات قاعدة البيانات أو آليات التسجيل.
3.مشكلة يمكن حلها باستخدام نمط التصميم”Singleton pattern”.
يحل هذا النمط مشكلتين في نفس الوقت، مما يخالف مبدأ المسؤولية الفردية:
نتأكد من أن الفصل يحتوي على مثيل واحد فقط.
فلماذا يريد أي شخص التحكم في عدد الحالات الموجودة في الفصل؟ السبب الأكثر شيوعًا لذلك هو التحكم في الوصول إلى بعض الموارد المشتركة، على سبيل المثال، قاعدة بيانات أو ملف.
وإلينا كيفية العمل: تخيل أننا قمنا بإنشاء كائن، ولكن بعد فترة قررت إنشاء كائن جديد. بدلاً من استلام كائن جديد، سنحصل على الكائن الذي قمنا بإنشائه بالفعل.
نلاحظ أنه من المستحيل تنفيذ هذا السلوك باستخدام مُنشئ عادي نظرًا لأن استدعاء المُنشئ يجب دائمًا أن يُرجع كائنًا جديدًا حسب التصميم.
توفير نقطة وصول عالمية لهذا المثيل.
هل نتذكر تلك المتغيرات العامة التي استخدمناها لتخزين بعض الكائنات الأساسية؟ على الرغم من أنها سهلة الاستخدام للغاية، إلا أنها أيضًا غير آمنة على الإطلاق نظرًا لأن أي رمز يمكن أن يحل محل محتويات تلك المتغيرات ويعطل التطبيق.
تمامًا مثل المتغير العام، يتيح لنا نمط Singleton الوصول إلى كائن ما من أي مكان في البرنامج. ومع ذلك، فهو يحمي هذا المثيل أيضًا من الكتابة فوقه بواسطة تعليمات برمجية أخرى.
هناك جانب آخر لهذه المشكلة: أننا لا نريد أن ينتشر الكود الذي يحل المشكلة رقم 1 في جميع أنحاء برنامجنا. فمن الأفضل أن يكون ذلك ضمن فئة واحدة، خاصة إذا كانت بقية التعليمات البرمجية الخاصة بنا تعتمد عليه بالفعل.
في الوقت الحاضر، أصبح نمط Singleton شائعًا جدًا لدرجة أن الناس قد يطلقون على شيء ما اسم Singleton حتى لو كان يحل مشكلة واحدة فقط من المشكلات المدرجة.
4.حل المشكلة باستخدام نمط التصميم”Singleton pattern”.
تشترك جميع تطبيقات Singleton في هاتين الخطوتين:
نجعل المنشئ الافتراضي خاصًا، لمنع الكائنات الأخرى من استخدام العامل الجديد مع فئة Singleton.
نقوم بإنشاء طريقة إنشاء ثابتة تعمل كمنشئ. ضمن الغطاء، تستدعي هذه الطريقة المنشئ الخاص لإنشاء كائن وحفظه في حقل ثابت. وتقوم كافة الاستدعاءات التالية لهذه الطريقة بإرجاع الكائن المخزن مؤقتًا.
إذا كان الكود الخاص بنت لديه حق الوصول إلى فئة Singleton، فيمكنه استدعاء الأسلوب الثابت الخاص بـ Singleton. لذلك كلما تم استدعاء هذا الأسلوب، يتم إرجاع نفس الكائن دائمًا.
تشبيه العالم الحقيقي
تعد الحكومة مثالاً ممتازًا لنمط Singleton.لا يمكن لأي دولة أن يكون لها سوى حكومة رسمية واحدة. وبغض النظر عن الهويات الشخصية للأفراد الذين يشكلون الحكومات، فإن عنوان “حكومة X” هو نقطة وصول عالمية تحدد مجموعة الأشخاص المسؤولين.
5.بناء نمط التصميم الإبداعي”Singleton pattern”.
- تعلن فئة Singleton عن الأسلوب الثابت get Instance الذي يُرجع نفس مثيل فئتها الخاصة.
يجب أن يكون مُنشئ Singleton مخفيًا من رمز العميل. يجب أن يكون استدعاء أسلوب
get Instance هو الطريقة الوحيدة للحصول على كائن Singleton.
- تمثيل نمط التصميم ” Singleton pattern” بشكل كود.
في هذا المثال، تعمل فئة اتصال قاعدة البيانات بمثابة Singleton. لا تحتوي هذه الفئة على مُنشئ عام، لذا فإن الطريقة الوحيدة للحصول على كائنها هي استدعاء طريقة get Instance. تقوم هذه الطريقة بتخزين الكائن الأول الذي تم إنشاؤه مؤقتًا وإرجاعه في كافة الاستدعاءات اللاحقة.
- قابلية تطبيق نمط التصميم”Builder pattern“.
- استخدم نمط Singleton عندما يكون للفصل الدراسي في البرنامج مثيل واحد فقط متاح لجميع العملاء، على سبيل المثال، كائن قاعدة بيانات واحد مشترك بين أجزاء مختلفة من البرنامج.
يقوم نمط Singleton بتعطيل كافة الوسائل الأخرى لإنشاء كائنات فئة ما باستثناء طريقة الإنشاء الخاصة. تقوم هذه الطريقة إما بإنشاء كائن جديد أو إرجاع كائن موجود إذا تم إنشاؤه بالفعل. - استخدم نمط Singleton عندما تحتاج إلى تحكم أكثر صرامة في المتغيرات العامة.
على عكس المتغيرات العامة، يضمن نمط Singleton وجود مثيل واحد فقط للفئة. لا شيء، باستثناء فئة Singleton نفسها، يمكن أن يحل محل المثيل المخزن مؤقتًا.
لاحظ أنه يمكنك دائمًا ضبط هذا القيد والسماح بإنشاء أي عدد من مثيلات Singleton. الجزء الوحيد من التعليمات البرمجية الذي يحتاج إلى التغيير هو نص طريقة get Instance.
- كيفية تنفيذ نمط التصميم“Singleton pattern“.
- نضيف حقلًا ثابتًا خاصًا إلى الفصل لتخزين المثيل المفرد.
- نقوم بتعريف طريقة إنشاء ثابتة عامة للحصول على المثيل المفرد.
- نقوم بتنفيذ “التهيئة البطيئة” داخل الطريقة الثابتة ويجب عليه إنشاء كائن جديد عند مكالمته الأولى ووضعه في الحقل الثابت. ويجب أن تقوم الطريقة دائمًا بإرجاع هذا المثيل في كافة الاستدعاءات اللاحقة.
- نجعل منشئ الفصل خاصًا. ستظل الطريقة الثابتة للفئة قادرة على استدعاء المُنشئ، وليس الكائنات الأخرى.
- نقوم بمراجعة رمز العميل واستبدل جميع الاستدعاءات المباشرة لمنشئ الوحدة الفردية باستدعاءات لطريقة الإنشاء الثابتة الخاصة به.
- إيجابيات وسلبيات نمط التصميم “Singleton pattern”.
الإيجابيات:
- يمكننا التأكد من أن الفصل يحتوي على مثيل واحد فقط.
- يمكننا الحصول على نقطة وصول عالمية إلى هذا المثيل.
- تتم تهيئة الكائن المفرد فقط عند طلبه لأول مرة.
السلبيات:
- ينتهك مبدأ المسؤولية الفردية. حيث أن النمط يحل مشكلتين في ذات الوقت.
- يمكن لنمط Singleton أن يخفي التصميم السيئ، على سبيل المثال، عندما تعرف مكونات البرنامج الكثير عن بعضها البعض.
- يتطلب النمط معالجة خاصة في بيئة متعددة الخيوط بحيث لا تقوم الخيوط المتعددة بإنشاء كائن مفرد عدة مرات.
- قد يكون من الصعب وحدة اختبار كود العميل الخاص بـ Singleton لأن العديد من أطر الاختبار تعتمد على الوراثة عند إنتاج كائنات وهمية. نظرًا لأن منشئ الفئة المفردة خاص وأن تجاوز الأساليب الثابتة أمر مستحيل في معظم اللغات، فسوف تحتاج إلى التفكير في طريقة مبتكرة للسخرية من المفردة. أو لا تكتب الاختبارات. أو لا تستخدم نمط Singleton.
- علاقات نمط التصميم”Singleton pattern”مع الأنماط الأخرى.
- غالبًا ما يمكن تحويل Facade إلى فئة Singleton نظرًا لأن كائن واجهة واحد يكفي في معظم الحالات.
- قد يكون Flyweight مشابهًا لـ Singleton إذا كان بإمكاننا بطريقة أو بأخرى تقليل جميع مثيلات الكائنات المشتركة إلى كائن واحد فقط من Flyweight ولكن هناك اختلافان أساسيان بين هذه الأنماط:
- يجب أن يكون هناك مثيل Singleton واحد فقط، بينما يمكن أن تحتوي فئة Flyweight على مثيلات متعددة بحالات جوهرية مختلفة.
- يمكن أن يكون كائن Singleton قابلاً للتغيير. أما كائنات Flyweight غير قابلة للتغيير.
- يمكن Abstract Factories, Builders and Prototypes كوحدات فردية Singletons.
- الخاتمة.
في الختام، يعد نمط تصميم Singleton بمثابة أداة قيمة في هندسة البرمجيات، خاصة لضمان وجود مثيل واحد فقط للفئة داخل التطبيق. ومع ذلك، ينبغي تناول استخدامه بحكمة، مع الأخذ في الاعتبار فوائده وعيوبه المحتملة حيث يوفر نمط Singleton مزايا مثل الوصول العالمي حيث يوفر نقطة وصول عالمية إلى مثيل واحد، مما يسهل الوصول إليه عبر التطبيق. وإدارة الموارد بحيث يمكن أن تكون مفيدة لإدارة الموارد التي يجب مشاركتها عبر التطبيق، مثل اتصالات قاعدة البيانات أو آليات التسجيل.
صيانة الحالة: تساعد في الحفاظ على حالة واحدة عبر التطبيق، مما يضمن الاتساق والتماسك.
ومع ذلك، هناك أيضًا تحديات مرتبطة بنمط Singleton بما في ذلك مشكلات التزامن وقد يؤدي ذلك إلى ظهور مشكلات التزامن، خاصة في البيئات متعددة الخيوط، إذا لم يتم تنفيذها بعناية. وأيضاً صعوبة الاختبار حيث يمكن أن يصبح الاختبار أكثر صعوبة بسبب الحالة العالمية التي يحتفظ بها مثيل Singleton.
ومشكلة الاقتران حيث يمكن أن يؤدي الإفراط في استخدام المفردات إلى اقتران محكم بين المكونات، مما يجعل قاعدة التعليمات البرمجية أقل نمطية ويصعب صيانتها.
وللتخفيف من هذه التحديات، يجب على المطورين النظر في أساليب بديلة، مثل dependency injection أو أنماط إبداعية أخرى مثل Factory Method أو dependency injection، اعتمادًا على المتطلبات المحددة للتطبيق. وباختصار، في حين أن نمط Singleton يوفر حلاً مناسبًا لبعض مشاكل التصميم، إلا أنه يجب دراسة استخدامه بعناية، ويجب استكشاف البدائل لضمان بنية برمجية جيدة التنظيم وقابلة للصيانة وقابلة للتطوير.
وبهذه المقالة نكون قد اختتمنا سلسلة أنماط التصميم الإبداعية في هندسة البرمجيات وسنبدأ في المقالات القادمة بالنوع الثاني من أنماط التصميم وهو أنماط التصميم الإنشائية.