مقاله

Strategy برای algorithmهای جایگزین‌پذیر؛ Observer برای notify — ارتباط با Event/Listener لاراول.

Strategy و Observer Pattern — رفتار قابل تعویض در PHP و Laravel

Strategy و Observer Pattern — رفتار قابل تعویض در PHP و Laravel

if/else برای هر نوع تخفیف، هر روش ارسال، هر درگاه پرداخت — Controller انفجار می‌کند. Strategy می‌گوید: رفتار را encapsulate و runtime عوض کن. Observer می‌گوید: وقتی X شد به Yها خبر بده — Laravel این را با Event/Listener و Eloquent Observer پیاده کرده.

Strategy Pattern

interface DiscountStrategy
{
    public function calculate(Order $order): int;
}

class PercentageDiscount implements DiscountStrategy
{
    public function __construct(private int $percent) {}

    public function calculate(Order $order): int
    {
        return (int) ($order->subtotal * $this->percent / 100);
    }
}

class FixedAmountDiscount implements DiscountStrategy
{
    public function __construct(private int $amount) {}

    public function calculate(Order $order): int
    {
        return min($this->amount, $order->subtotal);
    }
}
class OrderPricingService
{
    public function __construct(private DiscountStrategy $discount) {}

    public function total(Order $order): int
    {
        $discount = $this->discount->calculate($order);
        return $order->subtotal - $discount;
    }
}

در container:

$this->app->bind(DiscountStrategy::class, fn () => new PercentageDiscount(10));

Strategy vs match در Service

۲–۳ case: match کافی. ۱۰+ rule با تست جدا: Strategy/class جدا.

Observer Pattern (classic)

interface OrderObserver
{
    public function orderPlaced(Order $order): void;
}

class OrderSubject
{
    /** @var OrderObserver[] */
    private array $observers = [];

    public function attach(OrderObserver $observer): void
    {
        $this->observers[] = $observer;
    }

    public function place(Order $order): void
    {
        // save order
        foreach ($this->observers as $observer) {
            $observer->orderPlaced($order);
        }
    }
}

Laravel = Observer built-in

به‌جای manual attach:

  • OrderPlaced::dispatch($order) — domain observer
  • PostObserver::saved() — model lifecycle

Broadcast: WebSocket.

Strategy در Laravel واقعی

Filesystem disks (s3/local)، Mail drivers، Cache stores — همه strategy روی interface.

تست Strategy

it('applies percentage discount', function () {
    $service = new OrderPricingService(new PercentageDiscount(10));
    $order = new Order(['subtotal' => 1000]);
    expect($service->total($order))->toBe(900);
});

Unit test.

جمع‌بندی

Strategy = swap algorithm. Observer = notify many — در Laravel Event. Creational: Factory. SOLID: بعدی.

pricing engine