본문으로 건너뛰기

เนื้อหาภาษาไทย / 태국어 콘텐츠

시스템 가이드 검수 완료된 콘텐츠

Strategy Pattern: เลือก Algorithm ใน Runtime

บทความนี้แนะนำ Strategy Pattern ซึ่งเป็น Design Pattern ที่ช่วยให้เราสามารถเลือก Algorithm ที่ต้องการใช้งานได้ในขณะที่โปรแกรมกำลังทำงาน (Runtime) โดยไม่ต้องแก้ไ...

Strategy Pattern: เลือก Algorithm ใน Runtime

จากบทที่แล้วที่เราได้เรียนรู้เกี่ยวกับ Factory Pattern ที่ช่วยให้เราสร้าง Object ได้อย่างยืดหยุ่น โดยไม่ต้องระบุ Class ที่ต้องการสร้างโดยตรง ในบทนี้ เราจะมาทำความรู้จักกับอีกหนึ่ง Design Pattern ที่มีประโยชน์อย่างมาก นั่นคือ Strategy Pattern ที่จะช่วยให้เราสามารถเลือก Algorithm หรือพฤติกรรมที่ต้องการใช้งานได้ในขณะที่โปรแกรมกำลังทำงาน (Runtime) โดยไม่ต้องแก้ไขโค้ดหลัก

Strategy Pattern คืออะไร?

Strategy Pattern เป็น Design Pattern ประเภท Behavioral ที่ช่วยให้เรากำหนดกลุ่มของ Algorithm ที่สามารถสลับเปลี่ยนกันได้ และทำให้ Client สามารถเลือก Algorithm ที่ต้องการใช้งานได้ในขณะที่โปรแกรมกำลังทำงาน โดยไม่ต้องแก้ไขโค้ดของ Client เอง

หลักการทำงานของ Strategy Pattern:

  • กำหนด Interface หรือ Abstract Class ที่เป็นตัวกลางสำหรับ Algorithm ทั้งหมด
  • สร้าง Class ที่ Implement Interface หรือสืบทอด Abstract Class เพื่อเป็นตัวแทนของแต่ละ Algorithm
  • สร้าง Context Class ที่เก็บ Algorithm ที่เลือกใช้งาน และมี Method สำหรับเรียกใช้งาน Algorithm นั้น
  • Client สามารถเลือก Algorithm ที่ต้องการใช้งาน และกำหนดให้กับ Context Class

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

การใช้ Strategy Pattern มีข้อดีหลายประการ:

  • ความยืดหยุ่น: สามารถสลับเปลี่ยน Algorithm ได้ง่าย โดยไม่ต้องแก้ไขโค้ดหลัก
  • การแยกส่วน: Algorithm แต่ละตัวถูกแยกออกเป็น Class ทำให้โค้ดมีความชัดเจนและง่ายต่อการบำรุงรักษา
  • การ Reuse: Algorithm สามารถนำกลับมาใช้ใหม่ได้ใน Context Class อื่นๆ
  • ลดความซับซ้อน: ช่วยลดความซับซ้อนของโค้ด โดยการแยก Algorithm ออกจาก Context Class

การ Implement Strategy Pattern ใน PHP

เพื่อให้เข้าใจ Strategy Pattern มากยิ่งขึ้น เรามาดูตัวอย่างการ Implement ใน PHP กัน

ตัวอย่าง: ระบบการคำนวณภาษี

สมมติว่าเรามีระบบที่ต้องคำนวณภาษี โดยมี Algorithm การคำนวณภาษีหลายแบบ เช่น ภาษีมูลค่าเพิ่ม (VAT), ภาษีหัก ณ ที่จ่าย (Withholding Tax), และภาษีเงินได้บุคคลธรรมดา (Personal Income Tax) เราสามารถใช้ Strategy Pattern เพื่อให้ระบบของเราสามารถเลือก Algorithm การคำนวณภาษีที่เหมาะสมได้ใน Runtime

1. สร้าง Interface สำหรับ Strategy:

interface TaxStrategy {
    public function calculateTax(float $amount): float;
}

Interface TaxStrategy กำหนด Method calculateTax() ที่รับจำนวนเงินเป็น Parameter และคืนค่าภาษีที่คำนวณได้

2. สร้าง Class สำหรับแต่ละ Strategy:

class VATStrategy implements TaxStrategy {
    private float $vatRate;

    public function __construct(float $vatRate) {
        $this->vatRate = $vatRate;
    }

    public function calculateTax(float $amount): float {
        return $amount * $this->vatRate;
    }
}

class WithholdingTaxStrategy implements TaxStrategy {
    private float $withholdingRate;

    public function __construct(float $withholdingRate) {
        $this->withholdingRate = $withholdingRate;
    }

    public function calculateTax(float $amount): float {
        return $amount * $this->withholdingRate;
    }
}

Class VATStrategy และ WithholdingTaxStrategy Implement Interface TaxStrategy และกำหนด Algorithm การคำนวณภาษีของตัวเอง

3. สร้าง Context Class:

class TaxCalculator {
    private TaxStrategy $taxStrategy;

    public function __construct(TaxStrategy $taxStrategy) {
        $this->taxStrategy = $taxStrategy;
    }

    public function setTaxStrategy(TaxStrategy $taxStrategy): void {
        $this->taxStrategy = $taxStrategy;
    }

    public function calculateTax(float $amount): float {
        return $this->taxStrategy->calculateTax($amount);
    }
}

Class TaxCalculator เป็น Context Class ที่เก็บ Instance ของ TaxStrategy และมี Method calculateTax() ที่เรียกใช้งาน Algorithm การคำนวณภาษีของ Strategy ที่เลือกใช้งาน

4. ใช้งาน Strategy Pattern:

// เลือก Strategy การคำนวณภาษี
$vatStrategy = new VATStrategy(0.07); // VAT 7%
$withholdingTaxStrategy = new WithholdingTaxStrategy(0.03); // Withholding Tax 3%

// สร้าง TaxCalculator และกำหนด Strategy
$taxCalculator = new TaxCalculator($vatStrategy);

// คำนวณภาษี
$amount = 1000;
$vatTax = $taxCalculator->calculateTax($amount);
echo "VAT Tax: " . $vatTax . "\n"; // Output: VAT Tax: 70

// เปลี่ยน Strategy
$taxCalculator->setTaxStrategy($withholdingTaxStrategy);
$withholdingTax = $taxCalculator->calculateTax($amount);
echo "Withholding Tax: " . $withholdingTax . "\n"; // Output: Withholding Tax: 30

จากตัวอย่าง เราสามารถสลับเปลี่ยน Algorithm การคำนวณภาษีได้ง่ายๆ โดยการกำหนด Strategy ใหม่ให้กับ TaxCalculator โดยไม่ต้องแก้ไขโค้ดของ TaxCalculator เอง

ข้อดีและข้อเสียของ Strategy Pattern

ข้อดี:

  • Open/Closed Principle: สามารถเพิ่ม Algorithm ใหม่ได้ โดยไม่ต้องแก้ไขโค้ดที่มีอยู่
  • Single Responsibility Principle: Algorithm แต่ละตัวถูกแยกออกเป็น Class ทำให้โค้ดมีความชัดเจน
  • ความยืดหยุ่น: สามารถสลับเปลี่ยน Algorithm ได้ง่ายใน Runtime

ข้อเสีย:

  • ความซับซ้อน: อาจทำให้โค้ดมีความซับซ้อนมากขึ้น หากมี Strategy จำนวนมาก
  • Client ต้องรู้ Strategy ที่มี: Client ต้องทราบ Algorithm ที่มีอยู่ เพื่อที่จะเลือกใช้งานได้ถูกต้อง

เหตุผลเชิงออกแบบ, Trade-offs, และแนวปฏิบัติที่ดี

  • การเลือก Strategy: การเลือก Strategy ที่เหมาะสมขึ้นอยู่กับความต้องการของระบบ อาจใช้ Factory Pattern ร่วมกับ Strategy Pattern เพื่อช่วยในการสร้าง Strategy Instance
  • การจัดการ Strategy: หากมี Strategy จำนวนมาก อาจใช้ Service Locator หรือ Dependency Injection Container เพื่อช่วยในการจัดการ Strategy Instance
  • การทดสอบ: ควรทดสอบ Algorithm แต่ละตัวอย่างละเอียด เพื่อให้มั่นใจว่าทำงานได้อย่างถูกต้อง
  • Trade-offs: Strategy Pattern เพิ่มความยืดหยุ่น แต่ก็เพิ่มความซับซ้อนของโค้ดด้วย ควรพิจารณาความเหมาะสมกับขนาดและความซับซ้อนของระบบ

สรุป

Strategy Pattern เป็น Design Pattern ที่มีประโยชน์อย่างมากในการจัดการ Algorithm ที่สามารถสลับเปลี่ยนกันได้ ช่วยให้โค้ดมีความยืดหยุ่น ลดความซับซ้อน และง่ายต่อการบำรุงรักษา ในบทถัดไป เราจะมาเรียนรู้เกี่ยวกับ Observer Pattern ที่ช่วยให้เราสามารถแจ้งเตือน Object อื่นๆ เมื่อมีการเปลี่ยนแปลงเกิดขึ้น

Office.in.th Custom Service

이 구조를 바탕으로 시스템을 개발하거나 맞춤 변경하고 싶으신가요?

Office.in.th는 엔터프라이즈 웹 애플리케이션, API 연동, 공공/민간 업무 관리 시스템을 설계·개발하며 장기 지원을 제공합니다.

소프트웨어 개발 서비스 보기