Startgy Design Pattern

٣٠ نوفمبر ٢٠٢٤

تخيل انك بتبرمج في لعبة بتعمل سميلوشن للبط وعندك انواع كتيرة من البط وبدك تظهرهم وتخليهم يعملو صوت quacking فالطبيعي انك تيجي تعمل parent class الهم ونسميها Duck وبنعمل فنكشتين اللي هما quack للصوت و display لعرضهم وكل نوع من انواع البط بيورث من هاد النوع الاب وبس بيعمل override لل display بما انهم كلهم بط المنطقي كلهم نفس الصوت لقينا في السوق في العاب تانية وسوق لعبة البط بطل يمشي مفروض احنا نواكب التطور ونروح نطور من هاد اللعبة، اجو قالولك يا هندسة بدنا منك تخلي البط يصير يسبح ويطير انت قلتلهم عندي وروحت حطيت هالفنكشتين swim و fly في الكلاس الاب واجيت اعطيتهم هال demo رجعولك وقالولك معلش تعديل بسيط احنا عنا من ضمن البط في البطة المطاطية تاعت الاطفال بتطلع صوت صرير مش نفس صوت البط العادي وعنا البطة الخشبية وهادي بتعملش صوت وعنا ومش كل انواع البط بيطير فاللي بيطير الو اجنحة لكن اللي ملوش اجنحة بيطيرش فأنت كلمة تعديل بسيط عندك مشكلة معها فرحت رقعتها من عندك وكل اللي بيطيرش رحت عملت override ل fly وقلتلو تعملش اشي وقلت يلا مش مشكلة المطاطية هادي بنعمللها صوت لحالها وبرضو للي بيطلعوش صوت رحت عملت override ل quack وقلتلو تعملش اشي. تزكرت انك مش طوبرجي وانك حتلبس بالحيط لو طلبو كمان اشي فلقيت الاشي مش منطقي قلت معلش اتعب حالي وادور ع حل فقلت هات اعمل 2 interfaces واحد ل flyable وواحد ل quackable فيها فنكشن quack وقلت اي واحد بدو يطير بخليه يعمل implement ل flyable وبيعمل ovverrid ل fly ونفس الاشي للي بيطلع صوت وطبعا بما انهم كلهم بيطيرو بنفس الشكل فأنت كل مرة بدك تنسخ كود ال fly طب فرضا فرضا لقيت عندك مشكلة بدك تروح تعمل لفة على كل كلاس عمل implement ل flyable وتروح تعدل ع فنكشن ال fly تخيل قديش بدك وقت؟؟؟ طب نفكر شوية هيك بطريقة تانية لو رحنا احنا قلنا المشكلة وين كلها في fly behavior و quack behavior البطة يا بتطير يا بتطيرش والصوت عنا بيطلعو صوت البط العادي يا صوت الصرير زي المطاطية تاعت الاطفال يا بطلعوش صوت فرحت عملت FlyBehavior interface وقلت اللي هادي فيها فنكشن ال quack وعنا 3 sub classes يا Quack وهادي بتعمل صوت يا عنا Squeak وهادي تعمل صوت الصرير والتالت هوا ال MutedQuack وهادي بتعملش صوت ونفس الفكرة عملت FlyBehavior وحطيت فيه فنشكن fly وقلت عنا 2 sub classes عنا يا بطير FlyWithWings يا بتطيرش FlyNoWay هلقيت احنا بدنا كل نوع من انواع البط يقول كيف بينفذ ال fly behavior وال quack behavior وبما انو كل نوع بط صار بيحتوي على ال 2 behavior فصارت العلاقة has - a وهادي العلاقة composition فأحنا بنروح بنضيف متغيرين QuackBehavior quackBehavior; FlyBehaver flyBehavior; وعنا 2 فنشكنز وحدة اسمها performFly بتعمل call ل fly وبتكون زي مندوب عن ال fly behavior

function performFly(){
      return flyBehavior.fly();
}

وهادي بتعمل call ل والتانية performQuack بتعمل call ل quack وبتكون زي مندوب عن quack behavior

function performQuack(){
      return quackBehaver.quack();
}

هلقيت اي نوع من انواع البط حيعمل ovverrid على قيم flyBehaver و quackBehaver في constructor فمثلا عنا نعمل تاع الدمية المطاطية

class RubberDuck extends Duck {
    __construct() {
        quackBehaver = new Squeak();
        FlyBehavior = new FlyWithWings();
    }

    function display() {
        // display RubberDuck 
    }
}

هي وصلنا لطريقة مرنة لكيف نتعامل مع behaviors وكيف نعمل encapsulation لل behavior مختلفة وهاد اطلقو عليه اسم Startgy design pattern وهان بينت قوة composition في حال كان inheritance بيخلينا نعمل كود مش reusable هاد مش معناتو انو inheritance مش قوي لكن في هذه الحالة كان composition اكتر مرونة وقابلية للتوسع. "change behavior in runtime 😉"