التونسية للمحمــول Tn-GsMدخول


descriptionشرحأنماط التصميم في الجافا

more_horiz

لغة الجافا من أكثر لغات البرمجة تطوراً وأكبرها إنتشاراً وشهرة, ويمكن القول بإنها تكنولوجيا كاملة لا مجرد لغة برمجة فيمكن إستخدامها في العديد من المنصات وأنظمة التشغيل المختلفة والنظم المدمجة وغيرها ويمكن تخصيص آلة الجافا الإفتراضية (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 أيام الأخيرة..}

كتبت وقد أيقنت يوم كتابتي بأن يدي تفنى ويبقى كتابها فإن كتبت خيرا ستجزى بمثله وإن كتبت شراً عليها حسابها...
privacy_tip صلاحيات هذا المنتدى:
لاتستطيع الرد على المواضيع في هذا المنتدى
power_settings_newقم بتسجيل الدخول للرد