مقاله

پیاده‌سازی Singleton و Factory در PHP 8.3، anti-patternها و جایگزین Laravel container — بدون over-engineering.

Singleton و Factory Pattern در PHP — کی استفاده کنیم و کی نه

Singleton و Factory Pattern در PHP — کی استفاده کنیم و کی نه

Design Pattern نام الگوی تکرارشونده است — نه جادو و نه هدف مقاله. Singleton و Factory از Creational patterns هستند؛ در PHP و Laravel هر روز با آن‌ها برخورد می‌کنید، گاهی بدون اینکه نام ببرید. هدف این مقاله: تشخیص درست، نه پیاده‌سازی برای resume.

Factory Pattern — ساخت object بدون new پراکنده

کلاینت نمی‌داند کلاس concrete کدام است — factory بر اساس input می‌سازد.

interface PaymentGateway
{
    public function charge(int $amount): array;
}

class ZarinpalGateway implements PaymentGateway { /* ... */ }
class ZibalGateway implements PaymentGateway { /* ... */ }

class PaymentGatewayFactory
{
    public function make(string $driver): PaymentGateway
    {
        return match ($driver) {
            'zarinpal' => app(ZarinpalGateway::class),
            'zibal' => app(ZibalGateway::class),
            default => throw new InvalidArgumentException("Unknown driver: {$driver}"),
        };
    }
}

در Laravel معمولاً config/payment.php + binding در ServiceProvider همان کار را تمیزتر می‌کند — container خودش factory است.

Simple Factory vs Factory Method

Simple Factory: یک کلاس make(). Factory Method: subclass تصمیم می‌گیرد. در PHP عملی بیشتر Simple Factory + DI دیده می‌شود.

Singleton — یک instance در کل برنامه

class DatabaseConnection
{
    private static ?self $instance = null;

    private function __construct() {}

    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}

چرا Singleton در PHP/Laravel کمتر توصیه می‌شود

  • global state — تست سخت
  • مخفی کردن dependency
  • Laravel container singleton برای service کافی است: singleton() در provider
  • در PHP-FPM هر request process جدا — «true singleton» محدود
// Laravel way
$this->app->singleton(PaymentGatewayFactory::class);

Factory در Eloquent

User::factory()->create() — نام Factory اما الگوی test data — Factory Laravel.

کی Factory دستی بسازیم؟

چند implementation یک interface (gateway، SMS، storage driver). وگرنه config + container.

جمع‌بندی

Factory بله؛ Singleton دستی معمولاً نه — container. بعدی: Strategy و Observer. معماری: لایه‌ای.

refactor patterns