لغة الجافا من أكثر لغات البرمجة تطوراً وأكبرها إنتشاراً وشهرة, ويمكن القول بإنها تكنولوجيا كاملة لا مجرد لغة برمجة فيمكن إستخدامها في العديد من المنصات وأنظمة التشغيل المختلفة والنظم المدمجة وغيرها ويمكن تخصيص آلة الجافا الإفتراضية (JVM) لتناسب بيئة التشغيل المعينة التي نريد تشغيل جافا عليها مثل ما فعلت شركة قوقل بتخصيص ال JVM لبيئة الهواتف المحمولة في نظامهم الأندرويد وأطلقوا عليها Dalvik virtual machine , إذا فلغة جافا لغة مرنة جداً ويمكن تشغيلها في بيئات مختلفة ,, ولكن ينبغي على مبرمج من مبرمجي الجافا أن يكون على دراية بالطرق المناسبة لكتابة الكود البرمجي حتى لا تحدث المشاكل التي لا تُحمد عقباها.
ما هي أنماط التصميم ؟
نمط التصميم هو أفضل طريقة لحل مشكلة معينة تواجه كل مبرمج يستخدم لغة جافا, ويُتوصَّل إليها بالخبرات والتجارب
ويمكن تقسيم أنماط التصميم إلى ثلاث مجموعات تندرج تحت كل منها عدد من الأنماط :
1. نمط الإنشاء (Creational design pattern) :
هو الذي يهتم بإيجاد حلول لمشاكل إنشاء ال object بأفضل طريقة ممكنة بمعنى أنه ليس من المناسب إنشاء ال object بإستخدام الكلمة المحجوزة new في أي حالة أن يكون ذلك مناسباً فقد تحتاج في بعض الحالات أن تخفى طريقة الإنشاء من كل من يستخدم ال class الذي قمت بإنشاءه , وأيضاً في بعض الحالات ليس من المناسب أن تقوم بإنشاء object من ال class الذي تريد الوصول إلى وظائفه في كل مرة تنشئ object فقد يؤثر ذلك في الأداء. تندرج تحت هذا النمط 5 طرق وهي :
1. نمط Singleton
2. نمط Factory
3. نمطAbstract factory
4. نمط Builder
5. نمط Prototype
2. نمط الهيكلة (Structural design pattern ):
هي مجموعة الأنماط التي تهتم بتوفير حلول مختلفة لإنشاء هيكل ال class . وتندرج تحت هذا النمط 7 طرق وهي :
1. نمط Adapter
2. نمط Composite
3. نمط Proxy
4. نمط Flyweight
5. نمط Facade
6. نمط Bridge
7. نمط Decorator
3. نمط السلوك (Behavioral design pattern):
هي مجموعة الأنماط التي تهتم بتوفير حلول لأفضل طرق العلاقات بين ال objects . وتندرج تحت هذا النمط 11 طريقة وهي :
1. نمط Template method
2. نمط Mediator
3. نمط Chain of responsibility
4. نمط Observer
5. نمط Strategy
6. نمط Command
7. نمط State
8. نمط Visitor
9. نمط Interpreter
10. نمط Iterator
11. نمط Memento
وسأقوم بحول الله وقوته بشرح جميع هذه الأنماط في سلسلة متتالية من المقالات ونبدأ بالنوع الأول من الإنماط الإنشائية وهو نمط Singleton. وسأقوم بإتباع طريقة بسيطة في كل نمط وهي تعريف النمط – متى تستخدم – المشاكل التي تستطيع حلها بإستخدام هذا النمط – الطرق التي يتم بها تطبيق هذا النمط – مثال عملى للنمط – أين تم إستخدام النمط في مكتبة جافا الأساسية إن وجدت
نمط Singleton :
تعريفه : هو نمط يستخدم لإنشاء object واحد فقط من ال class يعني في كل مرة تريد الوصول لأي وظيفة من وظائف ال class يتم إستخدام نفس ال object المحجوز في الذاكرة ولا يتم إنشاء واحد جديد. وهذا النمط يمنع إنشاء ال object مباشرة بأن يقوم بعمل private constructor لل class
متى يستخدم ؟ يستخدم في حالات كثيرة منها logs و ال driver object مثل محركات قواعد البيانات وأيضاً في cashing وفي Thread Pool وغيرها كثير
ولكي تقوم بتطبيق هذا النمط يجب عليك مراعاة الآتي :
• ال constructor يجب أن يكون من نوع private حتى يمنع إنشاء ال object بطريقة مباشرة من خارج ال class بإستخدام الكلمة المحجوزة new
• متغير من نوع private static من نفس ال class والذي يتم عن طريقه إنشاء ال object من ال class
• دالة (method ) من نوع public static تقوم بإرجاع ال object من ال class حتى يتم الوصول إليها من أي class آخر
المشاكل التي تم حلها بإستخدام هذا النمط :
الطرق التي يمكن بها تطبيق نمط ال Singleton كثيرة وهي :
1. Eager Initialization :
في هذه الطريقة يتم إنشاء ال object في داخل جسم الكلاس وتقوم ال JVM بتحميله وإنشائه عند تحميل الكلاس بواسطة ال class loader
مثال
1 2 3 4 5 6 7 8 9 | الكود: public الكود: class الكود: EagerSingletonExample { الكود: private الكود: static الكود: final الكود: EagerSingletonExample instance = الكود: new الكود: EagerSingletonExample(); الكود: private الكود: EagerSingletonExample(){} الكود: public الكود: static الكود: EagerSingletonExample getInstance() { الكود: return الكود: instance; الكود: } الكود: } |
ولكن هذه الطريقة فيها بعض القصور وهي أنه يتم إنشاء ال object عندما يقوم ال JVM بتحميل الكلاس بواسطة ال class loader وحتى ولو لم يستخدم أحد هذا ال object يكون قد تم حجز مكان له في JVM
2. Static block initialization :
يشبه الطريقة السابقة ولكنه يقوم بإنشاء ال object في static block مما يسهل إضافة خيار معالجة الإستثناءات (exception handling)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | الكود: public الكود: class الكود: StaticBlockSingletonExample { الكود: private الكود: static الكود: StaticBlockSingletonExample instance; الكود: private الكود: StaticBlockSingletonExample(){} الكود: static الكود: { الكود: try الكود: { الكود: instance = الكود: new الكود: StaticBlockSingletonExample(); الكود: } الكود: catch الكود: (Exception e){ الكود: } الكود: } الكود: public الكود: static الكود: StaticBlockSingletonExample getInstance(){ الكود: return الكود: instance; الكود: } الكود: } |
وأيضاً هذه الطريقة في نفس المشكلة السابقة وهي أنه يتم إنشاء ال object حتى لو لم تقم بمناداة الدالة getInstance وذلك لأن عملية الإنشاء تمت في داخل جسم الكلاس وستقوم ال JVM بتنفيذه عند تحميل الكلاس بواسطة ال class loader
3. Lazy Initialization :
يتم فيها إنشاء ال object داخل الدالة getInstance نفسها وهذه الطريقة تحل المشكلة السابقة
مثال لها
1 2 3 4 5 6 7 8 9 10 | الكود: public الكود: class الكود: LazySingletonExample { الكود: private الكود: static الكود: LazySingletonExample instance ; الكود: private الكود: LazySingletonExample(){} الكود: public الكود: static الكود: LazySingletonExample getInstance(){ الكود: if الكود: (instance == الكود: null الكود: ) الكود: instance = الكود: new الكود: LazySingletonExample(); الكود: return الكود: instance ; الكود: } الكود: } |
هذه الطريقة ممتازة ولكن تظهر فيها المشاكل في الأنظمة متعددة العمليات multithreaded systems بالتحديد في حالة وصول أكثر من عملية thread للشرط if بداخل الدالة getInstance لأن ذلك سيؤدي إلى أن كل عملية thread سيكون عندها نسخة object مختلفة مما يخل بنمط ال singleton تماماً
4. Thread safe singleton :
هذه الطريقة تحل المشلكة السابقة في حالة أكثر من عملية thread بإستخدام الكلمة المحجوزة synchronized التي تسمح ل thread واحد فقط أن يقوم بتنفيذ الدالة في نفس الوقت, مثال
1 2 3 4 5 6 7 8 9 10 11 | الكود: public الكود: class الكود: ThreadSafeSingletonExample { الكود: private الكود: static الكود: ThreadSafeSingletonExample instance ; الكود: private الكود: ThreadSafeSingletonExample(){} الكود: public الكود: static الكود: synchronized الكود: ThreadSafeSingletonExample getInstance(){ الكود: if الكود: (instance == الكود: null الكود: ) الكود: instance = الكود: new الكود: ThreadSafeSingletonExample(); الكود: return الكود: instance; الكود: } الكود: } |
هذه الطريقة ممتازة جداً ولكنها تؤدي لتقليل الأداء نسبة لإستخدام ال synchronized ويمكننا معالجة ذلك بجعل ال synchronized داخل الشرط كالاتي :
1 2 3 4 5 6 7 8 9 | الكود: public الكود: static الكود: ThreadSafeSingletonExample getInstance(){ الكود: if الكود: (instance == الكود: null الكود: ){ الكود: synchronized الكود: (ThreadSafeSingletonExample. الكود: class الكود: ){ الكود: if الكود: (instance == الكود: null الكود: ){ الكود: instance = الكود: new الكود: ThreadSafeSingletonExample(); الكود: } الكود: } الكود: } الكود: } |
5. Bill Pugh singleton :
كل الطرق السابقة تظهر فيها المشاكل في حالة وجود عمليات threads كثيرة جداً تحاول مناداة الدالة getInstance في نفس اللحظة, المشاكل تكون في الذاكرة تحديداً , فجاءت هذه الطريقة بطريقة مختلفة لحل هذه المشكلة بإستخدام inner helper class مثال :
1 2 3 4 5 6 7 8 9 10 11 | الكود: public الكود: class الكود: BillPughSingletonExample { الكود: private الكود: BillPughSingletonExample(){}; الكود: private الكود: static الكود: class الكود: SingletonHelper { الكود: private الكود: static الكود: final الكود: BillPughSingletonExample INSTANCE = الكود: new الكود: BillPughSingletonExample(); الكود: } الكود: public الكود: static الكود: BillPughSingletonExample getInstance(){ الكود: return الكود: SingletonHelper.INSTANCE; الكود: } الكود: } |
مع ملاحظة أن الكلاس الداخلي SingletonHelper لايتم تحميله في ال JVM بواسطة ال class loader عند تحميل الكلاس BillPughSingletonExample بل يتم ذلك عند مناداة الدالة وهذه الطريقة هي أفضل طريقة لتطبيق مفهوم ال singleton لما فيها من حلول لأغلب المشاكل السابقة .
وعموماً يمكنك تطبيق ال singleton بطرق أخرى كثيرة لكن المهم أن لا يكون هناك أكثر من instance للكلاس
أين تم إستخدامه في مكتبة جافا الأساسية : ال singleton مستخدم في كثير من مكتبات الجافا وأقرب مثال له في ال java.lang.Runtime
وسأواصل في بقية الأنماط إن شاء الله تعالى.
▬▬▬▬▬▬▬▬ஜ ۩۞۩ ஜ▬▬▬▬▬▬▬▬
[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذه الصورة] قوانين منتدى التونسية للمحمول ( المرور من هنا واجب )
[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذه الصورة] طريقة الإنظمام إلي مجموعة أعضاء سبور € GSM Tn
[ندعوك للتسجيل في المنتدى أو التعريف بنفسك لمعاينة هذه الصورة] هام لكل الأعضاء الجدد {اخي ..}، كنت عضومنذُ{8 أيام الأخيرة..}
كتبت وقد أيقنت يوم كتابتي بأن يدي تفنى ويبقى كتابها فإن كتبت خيرا ستجزى بمثله وإن كتبت شراً عليها حسابها...