概念
使わない実装
- 分岐が増えて困る
- 修正漏れの可能性
- ただの文字列なので静的解析も効かないので大変そう
<?php
// 決済処理を行うクラス
class OrderProcessor
{
public function __construct(
private float $amount
) {}
// 決済方法が増えるたびに、このメソッドの中に if/case が増えていく
public function processPayment(string $method): void
{
if ($method === 'credit_card') {
echo "クレジットカード決済で ¥" . $this->amount . " を支払いました。\n";
} elseif ($method === 'paypay') {
echo "PayPay決済で ¥" . $this->amount . " を支払いました。\n";
} else {
echo "未対応の決済方法です。\n";
}
}
}
// --- 実行コード ---
$order = new OrderProcessor(1500);
// 決済方法の文字列を渡して実行
$order->processPayment('credit_card');
$order->processPayment('paypay');
使う実装
- 決済を実行するだけのクラスと、決済方法のクラスを分けて、もらったものを実行するだけ
- 方法をいくらでも増やせそう
<?php
// 1. 共通のインターフェース(作戦のルール)を決める
interface PaymentStrategy
{
public function pay(float $amount): void;
}
// 2. 具体的な決済方法(作戦A)をクラス化
class CreditCardPayment implements PaymentStrategy
{
public function pay(float $amount): void
{
echo "クレジットカード決済で ¥" . $amount . " を支払いました。\n";
}
}
// 3. 具体的な決済方法(作戦B)をクラス化
class PayPayPayment implements PaymentStrategy
{
public function pay(float $amount): void
{
echo "PayPay決済で ¥" . $amount . " を支払いました。\n";
}
}
// 4. 決済を実行する本体(コンテキスト)
class OrderProcessor
{
public function __construct(
private float $amount
) {}
// 決済を実行するメソッド(引数で「どの作戦(オブジェクト)を使うか」を受け取る)
public function processPayment(PaymentStrategy $paymentMethod): void
{
// 使う側は if文を持たず、渡されたオブジェクトの pay() を呼ぶだけ
$paymentMethod->pay($this->amount);
}
}
// --- 実行コード ---
$order = new OrderProcessor(1500);
// クレジットカードで支払う場合(オブジェクトを直で渡す)
$order->processPayment(new CreditCardPayment());
// PayPayで支払う場合
$order->processPayment(new PayPayPayment());
絵
