Strategy Pattern 策略模式

Posted by Elizabeth Huang on Thu, Mar 19, 2026

簡介

公司專案因為商業邏輯較複雜,常會遇到有多種方式處理同一件事的場景。例如網購場景,對主流程而言都要付款和配送,但付款有信用卡、LINE pay 等方式,配送有宅配或超取等選項
這時就可以考慮使用策略模式:

  1. 從外部來看,只需要知道流程,不需要知道內部不同的策略如何實作,避免在主流程中有大量 if else 和重複的 code
  2. 每個策略有各自的 class,切分後邏輯更清晰不混雜,有新的策略就新增一個 class,特定策略需要更改只需修改它的 class,不會動到其他策略及主流程
  3. 避免多個人同時改動相同幾個 class,最後解衝突解到頭痛

如上述的網購場景,以下爲 PHP 實作範例,有信用卡和 LINE pay 兩種付款方式,都可以退款,並且退款還有一些共用的後續操作

另外,個人習慣策略模式配合簡單工廠建立指定的 class。並且若有共用邏輯可改用 abstract 而不是 interface

 1enum PayType: int {
 2    case CARD = 1;
 3    case LINE = 2;
 4}
 5
 6abstract class PaymentService
 7{
 8    public abstract function pay();
 9    public abstract function refund();
10    public function handleRefund()
11    {
12        $this->refund();
13        echo "進行其他共用操作\n";
14    }
15}
16
17class Card extends PaymentService
18{
19    public function pay()
20    {
21        echo "信用卡 付款\n";
22    }
23
24    public function refund()
25    {
26        echo "信用卡 退款\n";
27    }
28}
29
30class Line extends PaymentService
31{
32    public function pay()
33    {
34        echo "LINE PAY 付款\n";
35    }
36
37    public function refund()
38    {
39        echo "LINE PAY 退款\n";
40    }
41}
42
43class PaymentFactory
44{
45    public static function create(PayType $payType): PaymentService
46    {
47        return match ($payType) {
48            PayType::CARD => new Card(),
49            PayType::LINE => new Line(),
50            default => throw new \UnexpectedValueException('無效的付款方式'),
51        };
52    }
53}
54
55$request = ['pay_type' => 1];
56$paymentService = PaymentFactory::create(PayType::from($request['pay_type']));
57$paymentService->pay();
58$paymentService->handleRefund();
59
60// output:
61// 信用卡 付款
62// 信用卡 退款
63// 進行其他共用操作