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 observerPostObserver::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);
});
جمعبندی
Strategy = swap algorithm. Observer = notify many — در Laravel Event. Creational: Factory. SOLID: بعدی.