[Design Pattern] Strategy Pattern in Depth

วันนี้ Blog นี้มาเน้นทางสาย Pattern กันเยอะ เชื่อว่าหลายๆคน Copy & Paste Development มาใช้งาน แต่ก็ไม่รู้ว่า มัน คือ อะไรครับ โดย Pattern ที่ผมมาเขียนลง Blog ในวันนี้ คือ Strategy Pattern ซึ่งข้อมูลส่วนใหญ่ผมเอามาจากของ Head First นะครับ ตัวอย่างมันอธิบายได้ง่ายดีครับ

ทำไมต้องใช้ Strategy

  • ทุกปัญหามันไม่สามารถแก้ไขด้วยกับใช้เทคนิคเดิมของ OOP - Inheritance ได้ไง ? ตัวอย่าง เช่น นายเจมส์ได้รับหน้าที่ในการสร้าง Class ของ Duck (เป็ด)  โดยที่เป็ดแต่ละชนิดมีพฤติกรรมที่แตกต่างกับครับ โดยที่เรา Design ไว้ให้ใช้มีพฤติกรรมที่ Class แม่ แล้วให้ Class ลูกสืบทอด(Inheritance) ไปใช้ครับ
  • ซึ่งพอมีชนิดของเป็ดที่หลากหลายขึ้น ดันเกิดข้อขัดแย้งต้องมา Override แก้ไขพฤติกรรมมันซะงั้น จริงๆ มันควรทำอย่างนั้นเหรอ (ลูกดื้อ เปลี่ยนพฤติกรรมของแม่)
  • ในเมื่อ Inheritance (IS-A) มันไม่ Work ต้องเปลี่ยนมาเป็นการประกอบร่าง composition (HAS-A)

เมื่อไหร่ควรจะใช้

  • เมื่อต้องการเพิ่ม Maintainability - เลือกประกอบสิ่งที่สนใจได้ ตอน Runtime เช่น MullarDuck ตอนอายุน้อยกว่า 14 วัน ยังบินไม่ไม่ได้นะ แต่ถ้ามากกว่านั้น เราสามารถ Set ความสามารถบิน (FlyWithWings) เพิ่มเข้าไปได้
  • งานชิ้นเดียวกัน แต่มีวิธีการคิด (Algorithm/Behavior) ที่หลากหลาย เช่น
    • การจ่ายค่าโดยสารรถเมล์ ซึ่งแต่ละรุ่นมีวิธีคิดที่แแตกต่างกัน
    • การเดินหมากรุก ซึ่งหมากแต่ละตัวตอนเดิน กับการถูกกิน มันมีกฏที่แตกต่างกันไป
  • Keyword
    • Interface - เป็นสัญญาว่า เรารู้จักกันนะ
    • Delegation - สั่งงาน ใครคนอื่นททำต่อ เช่น
      • เดิม - Duck จัดการวิธีการบินเองหมด
      • ใหม่ - เพิ่มความสามารถ จาก Class FlyWithWings แล้วสั่งให้ Class FlyWithWings ไปจัดการต่อ

Pattern มันเป็นอย่างไร - Class Diagram

  • Duck เป็นผู้สั่งการ แต่ไม่ได้สั่งผ่าน Class โดยตรงนะ แต่ Duck รู้จักกันผ่าน Interface ตามเส้นสีแดงใน Class Diagram เลย
  • จาก Class Diagram แต่ละชิ้นคล้ายเป็นส่วนประกอบ (composition) ขึ้นมาแทน

มุมมองตอน Runtime - Object Diagram

  • Mallard Duck
  • Rubber Duck


มุมมองลำดับการทำงาน - Sequence Diagram

  • สร้างผ่าน Constructor มาดู Code เทียบกับ Sequence Diagram ไปกันเลย
public class MallardDuck extends Duck {
   public MallardDuck() {
      flyBehavior = new FlyWithWings();
      quackBehavior = new Quack();
   }

   public void display() {
      System.out.println(“I’m a model duck”);
   }
}
  • Client มา Set พฤติกรรมลงไปเอง มาลุยกันครับ
======================================================
/* CLASS */
public class MallardDuck extends Duck {
   public MallardDuck() 
   {
      //DO Nothing
   }
   public void display() 
   {  
      System.out.println(“I’m a Mallard Duck”);
   }
}
======================================================
/* CLIENT */
public class DuckSimulator {
   public static void main(String[] args) {
      //Client Do Anything
      Duck model = new MallardDuck();
      model.setFlyBehavior(new FlyWithWings());
      model.setFlyBehavior(new Quack());
   }
}
  • ตอนลองสั่งให้บิน โดยแสดงให้เห็นถึง Delegation ถ้าสาย Dev ดู Code ดีกว่าครับ
======================================================
/* CLASS */
public abstract class Duck {
   FlyBehavior flyBehavior;

   //Some Code
   public void performFly() {
      flyBehavior.fly();
   }
}
======================================================
/* CLIENT */
public class DuckSimulator {
   public static void main(String[] args) {
      //Client Do Anything
      Duck model = new MallardDuck();
      model.performFly();
   }
}

Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts to your email.