簡介
公司專案因為商業邏輯較複雜,常會遇到有多種方式處理同一件事的場景。例如網購場景,對主流程而言都要付款和配送,但付款有信用卡、LINE pay 等方式,配送有宅配或超取等選項
這時就可以考慮使用策略模式:
- 從外部來看,只需要知道流程,不需要知道內部不同的策略如何實作,避免在主流程中有大量 if else 和重複的 code
- 每個策略有各自的 class,切分後邏輯更清晰不混雜,有新的策略就新增一個 class,特定策略需要更改只需修改它的 class,不會動到其他策略及主流程
- 避免多個人同時改動相同幾個 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// 進行其他共用操作