Skip to content
intermediate Phase 9 · DI & Patterns

Factory Pattern

Factory, Abstract Factory, and Simple Factory patterns with PHP examples and Magento's Factory classes

45m
0 problems
Topic Progress 0%

Simple Factory

What is a Simple Factory?

A Simple Factory encapsulates object creation logic in a single method. It's not a formal GoF pattern but widely used.

namespace Vendor\Payment\Factory;

use Vendor\Payment\Model\Gateway;

class PaymentGatewayFactory
{
    public function create(string $type): GatewayInterface
    {
        return match ($type) {
            'stripe' => new StripeGateway(
                $this->config->getStripeKey()
            ),
            'paypal' => new PayPalGateway(
                $this->config->getPayPalClientId(),
                $this->config->getPayPalSecret()
            ),
            'bank_transfer' => new BankTransferGateway(),
            default => throw new \InvalidArgumentException(
                "Unknown payment gateway: {$type}"
            ),
        };
    }
}

// Usage
$gateway = $factory->create('stripe');
$gateway->charge(29.99);

When to Use Simple Factory

  • Creating objects based on configuration (payment methods, shipping carriers)
  • The creation logic is simple (2-5 branches)
  • You don't need multiple factory implementations

Factory Method Pattern

What is Factory Method?

Factory Method defines an interface for creating objects but lets subclasses decide which class to instantiate.

namespace Vendor\Catalog\Export;

// Abstract creator
class AbstractProductExporter
{
    abstract protected function createFormatter(): FormatterInterface;

    public function export(array $products): string
    {
        $formatter = $this->createFormatter();
        return $formatter->format($products);
    }
}

// Concrete creators
class CsvProductExporter extends AbstractProductExporter
{
    protected function createFormatter(): FormatterInterface
    {
        return new CsvFormatter();
    }
}

class JsonProductExporter extends AbstractProductExporter
{
    protected function createFormatter(): FormatterInterface
    {
        return new JsonFormatter();
    }
}

When to Use Factory Method

  • Subclasses need to decide which object to create
  • You want to localize creation logic in subclasses
  • The framework controls extension points

Abstract Factory Pattern

What is Abstract Factory?

Provides an interface for creating families of related objects without specifying concrete classes.

namespace Vendor\Theme\Factory;

interface ComponentFactoryInterface
{
    public function createHeader(): HeaderInterface;
    public function createFooter(): FooterInterface;
    public function createSidebar(): SidebarInterface;
}

// Desktop family
class DesktopComponentFactory implements ComponentFactoryInterface
{
    public function createHeader(): HeaderInterface
    {
        return new DesktopHeader(); // Wide, full navigation
    }

    public function createFooter(): FooterInterface
    {
        return new DesktopFooter(); // Multi-column footer
    }

    public function createSidebar(): SidebarInterface
    {
        return new DesktopSidebar(); // Fixed sidebar
    }
}

// Mobile family
class MobileComponentFactory implements ComponentFactoryInterface
{
    public function createHeader(): HeaderInterface
    {
        return new MobileHeader(); // Hamburger menu
    }

    public function createFooter(): FooterInterface
    {
        return new MobileFooter(); // Simplified footer
    }

    public function createSidebar(): SidebarInterface
    {
        return new MobileSidebar(); // Slide-out drawer
    }
}

// Usage: client code uses the interface
function renderPage(ComponentFactoryInterface $factory): void
{
    $header = $factory->createHeader();
    $footer = $factory->createFooter();
    $sidebar = $factory->createSidebar();
    // Render page with consistent component family
}

The client doesn't know if it's rendering desktop or mobile — the factory family ensures consistency.

Magento's Auto-Generated Factories

How Magento Factories Work

Magento automatically generates factory classes for any injectable class. You don't write them — they're generated in var/di/.

namespace Vendor\Catalog\Model;

// Magento auto-generates this factory
class ProductFactory
{
    public function __construct(
        private \Magento\Framework\ObjectManager\ObjectManager $objectManager,
        private string $instanceName = 'Magento\Catalog\Model\Product'
    ) {}

    public function create(array $data = []): Product
    {
        return $this->objectManager->create($this->instanceName, $data);
    }
}

Using Magento Factories

namespace Vendor\Import\Model;

class ProductCreator
{
    public function __construct(
        private \Magento\Catalog\Model\ProductFactory $productFactory,
        private \Magento\Catalog\Api\ProductRepositoryInterface $productRepo
    ) {}

    public function createProduct(array $data): \Magento\Catalog\Api\Data\ProductInterface
    {
        // Factory creates new instance with constructor args
        $product = $this->productFactory->create([
            'data' => $data,
        ]);

        $product->setSku($data['sku']);
        $product->setName($data['name']);
        $product->setPrice($data['price']);

        return $this->productRepo->save($product);
    }
}

Why Factories Exist in Magento

Magento uses the Object Manager to create objects with complex dependency graphs. Factories:

  1. Encapsulate creation logic — constructor args are resolved automatically
  2. Create new instances on demand — unlike DI which shares instances
  3. Support runtime data — pass different data for each new object
// DI gives you ONE shared instance
public function __construct(
    private ProductRepositoryInterface $productRepo // one instance
) {}

// Factory gives you NEW instances each time
public function __construct(
    private ProductFactory $productFactory // creates new Products
) {}

Quiz

1. What is the key difference between Factory Method and Abstract Factory?

Question 1 options

2. When should you use Magento's auto-generated factories instead of direct DI?

Question 2 options

3. How does Magento generate factory classes?

Question 3 options

Flashcards

Question

What does a Simple Factory do?

Answer

Encapsulates object creation in a single method based on input type

Question

What is the Factory Method pattern?

Answer

Subclasses decide which class to instantiate via an abstract creation method

Question

What is an Abstract Factory?

Answer

Creates families of related objects without specifying concrete classes

Question

When to use Magento factories vs DI?

Answer

Factories for new instances with runtime data; DI for shared dependencies

Revision Notes

Key Takeaways

  • 1. Simple Factory: one method, switch-based creation
  • 2. Factory Method: subclasses decide which class to create
  • 3. Abstract Factory: creates families of related objects
  • 4. Magento auto-generates factories for injectable classes
  • 5. Factories = new instances on demand; DI = shared instances

Interview Tips

  • Know the difference between all three factory variants
  • Explain when Magento factories are necessary vs over-engineering
  • Give a real example: ProductFactory for creating products during import

Cheat Sheet

Simple Factory     → create(type) with switch/match
Factory Method     → abstract createProduct(); subclasses override
Abstract Factory   → createHeader() + createFooter() + createSidebar()
Magento Factory    → auto-generated, creates new instances via ObjectManager

Use when: creating multiple objects with different runtime data
Skip when: DI gives you the shared instance you need