الشرح هيكون بطريقة بسيطة بحيث اي حد يقدر يفهم ان شاء الله. وكل تدوينة بتشرح pattern هتكون self-contained لوحدها يعني مش هتحتاج تقرا حاجه تانيه قبلها , الا بس لو لسه مش عارف يعني ايه design pattern وايه فايدتها وليه تستخدمها اقرا الـintro الاول من هنا:
الـ Strategy Pattern
ندخل
فالموضوع علي طول , احسن طريقة من وجهة نظري لفهم اي design pattern هي مثال عليه. فالأول هنشوف مثال وهنشوف الدنيا
من غير design pattern هتبقي عاملة ازاي و ايه مشاكلها وازاي الـstrategy هتحلها و تديك فوايد تانيه عليها كمان. الأمثلة
هتكون جافا بس لو متعرفش جافا متقلقش الدنيا هتكون بسيطة يكفي معرفتك بالـ OOP
المثال: افترض ان عندك class dog وواحد تاني bird و ليهم parent للحيوانات عموما اسمها animal الاتنين subclasses منها.
و animal فيها الصفات المشتركة
للحيوانات عموما زي ان كلها ليها اسم و طول و وزن وسرعة وهكذا وكمان عندها التصرفات
behavior المشتركة بتاعة الحيوانات زي انها بتتحرك وبتاكل
وتتنفس مثلا.
وعملنا override لـلـ move( ) function في الـ bird class لأن الطائر
بيتحرك بطريقة مختلفة غير بقية الحيوانات و عملنا extend لـ fucntion جديدة في dog class بتخليه يحفر
حفرة dig hole( )
دي مجموعة حاجات عشوائية هنبني عليها المثال بتاعنا.
Animal.java
Bird.java
Dog.Java
عاوزين ندي الـ
bird والحيوانات اللي كلها subclasses من animal القدرة عالطيران
دلوقتي هنتعامل بحاجات الـ oop اللي احنا
عارفينها كأننا منعرفش design patterns و دي الجزئية
اللي هنتخيل فيها الـ Bad code
الطبيعي و اول حاجه اي حد هيفكر فيها هي انه يضيف method fly( ) في animal class اللي هي الـ parent اللي كل
الـحيوانات بتـ inhert منها.
طيب ليه ده يعتبر bad code ؟
اوعي ابدا تضيف اي method لـ parent زي animal لو مش بتنطبق علي كل الـ childs بتوعها , لازم
تفرق بين الاختلافات بتاعة الـ childs ومابين الـ parent بتاعها.
ممكن حد يفكر طيب ما انا ممكن اضيفها فالـ parent عادي و اجي في class زي dog اللي مبيطرش و
أجي اعمل override للـ method دي و احط implementation مختلف !
لأن مش صح انك تفرض action معين علي كل الـ childs اللي معندهمش القدرة علي الطيران وكمان لأننا هنضطر كل اما نعمل اي حيوان جديد اننا نعمل override للـ method دي. (فكر دايما في Less code )
واحد هيسأل سؤال تاني: طيب ليه منحطش الـ method دي جوا الـ bird نفسها و نريح
دماغنا ؟
ببساطة لأن هيبقي عندك كود متكرر كتير جدا لو في animals تانيه هيكون
عندها القدرة علي الطيران , وبكده تبقي بتنافي مبدأ انك كـ professional تكتب less code وكمان لو اي
حيوان مالحيوانات تطور وبقي عنده القدرة عالطيران هتفضل تعدل فيه يبقي انت كده
بتنافي مبدأ تاني انك تكون professional وهو الـ maintainablilty , واحد هيقولي
وهو الكلب هيطير ؟
ده احتماله ضعيف فالـ real world فعلا بس افترض معايا انك بتبرمج لعبة وفي level ما الكلب بقي
عنده القدرة عالطيران ؟ ساعتها هتضطر تكرر نفس الكود.
واحد تاني ممكن يفكر اعمق شوية ويقول انا ممكن اعمل interface و ليكن flys مثلا واخلي كل
الـ childs ينفذوه بطريقتهم وده برضه غلط مش لنفس السبب.
مبدأين أساسيين لازم تحطهم في دماغك دايما وانت بتكتب كود:
- ابعد عن اي حاجه تخليك تعمل تكرار فالكود.
- ابعد عن اي حاجه تخلي ان تغير في class يأثر علي بقية الـ classes , اي تغيير فالـ parent المفروض ميبوظش الكود بتاع الـ childs والعكس صحيح.
لو لاقيت اي موقف بتعمل فيه حاجه من الاتنين دول يبقي انت بتفكر فالموضوع
بطريقة مش صح وبتكتب bad code.
طيب الـ Strategy Pattern ممكن تحللنا المشكلة دي ازاي ؟
ليه دي فكرة حلوة ؟الفكرة هنا اننا غلفنا كلalgorithm بتاع behavior معي زي اللي يقدر يطير واللي ميقدرش كل واحد جوا class لوحده وبكده نقدر نعمل مليون طريقة للطيران بدون ما نأثر علي animal او اي subclass ليها , ببساطة لأننا فصلنا الـ behavior عن الـ clients اللي هما الـ classes بتوع الحيوانات في حالتنا دي.
دلوقتي نقدر نضيف Instance Variable من نوع الـ interface flys جوا الـ parent class اللي هي animal ونقدر لكل child class نديله القدرة او عدم القدرة عالطيران اللي هما ال 2 classes اللي
عملناهم ItFlys و CantFly كالأتي:
اول حاجه عملت Instance Variable في الـ parent من نوع الـ interface Flys و سميته flyingTybe.
معلومة سريعة: دي حاجه اسمها composition وهو ان الـ class بدل ما تاخد الـ abilities بتاعتها عن طريق الـ inheritance بتشيل objects من انواع تانيه موجودة فيها الـ abilities دي built-in.
الـ composition ليه ميزة تانيه رهيبة جدا وهو انه بيمكنك
تغير الـ behavior في اي وقت اثناء الـ run time و بدون اي side- effect علي الـ subclasses او الـ super classes
يعني لو حيوان ما معندوش
القدرة عالطيران وفجأة طلعله جناجات تقدر تغير الـ flyintTybe بتاعه من CantFly تخليه ItFlys من غير ما تحتاج
تعدل اي حاجه تانيه.
تاني حاجه اننا عملنا method وسميناها tryToFly( )
وجواها ناديت علي function fly( ) بتاعة الـ flyingTybe object ايا كان نوعه بقي لأن فالنهاية
كل الـ algorithms اللي هيا CantFly و ItFlys كلهم subclasses من الـ interface Flys.
وبعد كده عملت setter للـ flyingTybe وسميته setFlyingAbility بياخد object من النوع Flys او اي subclass ليه
بعد كده كل اللي محتاج اعمله سوا ء في Dog calss او Bird class بسيط جدا وهو اني اساوي قيمة الـ flyingTybe بنوع من اتنين يا ItFlys يا CantFly و هنا تظهر قيمة الـ polymorphism لأن flyingTybe هو object من نوع الـ interface Flys لكن في نفس الوقت لما اساويه بأي subclass للـ interface و انادي علي method fly( ) هينادي الـ method بتاعة الـ subclass
فببساطة كل اللي هنعمله اننا هندخل جوا الـ constructors بتاع كلا من bird , dog وهكتب سطر كود جوا كل واحد فيهم (less
code) وهيبقي شكلهم كالأتي:
Dog.java
Bird.java
ودلوقتي بقي نجرب الكلام ده فالـ main ونعمل run ونشوف الناتج
Main.java
عملت 2 objects من نوع animal وعلمت واحد بـ new dog وسميته sparky و واحد بـ new bird وسميته tweety وبعد
كده طبعت الناتج بتاع الـ TrytoFly( ) بتاعة sparky و tweety وده كان الـ output:
Dog: I Can’t
fly
Bird:
Flying High
طيب لو فجأة الكلب قرر يطور من نفسه ويطير ؟
هنا تظهر ميزة تانيه للـ strategy
pattern وهي انك تقدر تغير الـ behavior بتاع الـ objects فالـ runtime كالاتي:
مجرد اني ناديت الـ method اللي اسمها setFlyingAbility( ) واديتها new ItFlys الكلب بقي عنده القدرة يطير
(Thanks
to polymorphism)
وده شكل الـ out put :
Dog: I Can’t
fly
Bird:
Flying High
Dog: Flying
High
كده المثال خلص , نبص عليه بصة شاملة عن طريق
Uml diagram وبعدين نطلع الـ concept بتاع الـ strategy pattern من المثال.
الملخص: عندنا parent اسمه animal فيه instance variable اسمه flyingTybe من نوع الـ interface Flys و الـ + فالـ uml يعني public وعندنا 2 childs اسمهم Bird & Dog و عملنا 2
Algorithms وعملنالهم encapsulate جوا 2 classes اللي هما CantFly & ItFlys و بقوا interchangeable يعني الحيوانات تقدر تبدل بينهم بطريقة seamless فالـ runtime.
الـ Strategy Concept
ببساطة هو إنك تعرف مجموعة من الـAlgorithms وتـ encapsulate كل واحدة لوحدها وتبدل بينهم dynamically مع اختلاف الـ scenario . يعني بتمكنك تغير الـ
Algorithm بطريقة مستقلة بعيدا عن الـ clients اللي بيستخدموها.
طيب امتي تستخدم الـ Strategy Pattern ؟
لما تكون محتاج تعرف Class هيكون عندها behavior مشابه لـ مجموعة behaviors تانيه. يعني في المثال بتاعنا الحاجه المشتركة
هي فكرة الطيران سواء القدرة او عدم القدرة عليهم او مثلا انهم بيطيروا بطرق
مختلفة.
خليني اوضحها بطريقة ابسط شوية
استخدم الـ strategy pattern لما تكون عاوز تدي الـ objects بتاعتك القدرة علي انها تختار بين مجموعة behaviors زي مثلا
- Fly with wings
- Don’t fly
- Flay fast
واكيد تستخدم الـ Strategy لما تكون محتاج تغير بين الـ behaviors بطريقة dynamic
وكمان شوية هتحس بيها مع الاستخدام حاجات
تانيه زي:
- بتقلل استخدمك لـ conditions طويلة
- بتقلل تكرار الكود
- لما بتغير في class مبتأثرش علي بقية الـ classes
- تقدر تخفي secret code جواها عن الـ user
عيبها الوحيد انها بتزود
عدد الـ classes و الـ objects وده ميعتبرش عيب مؤثر.
لو عندك أي تعليق او سؤال ممكن تعمل كومنت بالـ facebook بتاعك تحت التدوينة و ممكن تبعتلي علي الـ facebook بتاعي من هنا. ولو الموضوع ممكن يفيد حد من اصدقائك اعمله share.
لو عندك أي تعليق او سؤال ممكن تعمل كومنت بالـ facebook بتاعك تحت التدوينة و ممكن تبعتلي علي الـ facebook بتاعي من هنا. ولو الموضوع ممكن يفيد حد من اصدقائك اعمله share.
Blogger Comment
Facebook Comment