Design Patterns for Web Developers

matt
Matthew Gros · Aug 19, 2025

TLDR

Repository for data access, Strategy for swappable algorithms, Observer for events, Factory for object creation.

Design Patterns for Web Developers

Patterns Solve Common Problems

Don't over-engineer. Use patterns when they fit.

Repository Pattern

Abstract data access:

interface UserRepositoryInterface
{
    public function find(int $id): ?User;
    public function findByEmail(string $email): ?User;
    public function save(User $user): void;
}

class EloquentUserRepository implements UserRepositoryInterface
{
    public function find(int $id): ?User
    {
        return User::find($id);
    }
}

// In controller
public function __construct(
    private UserRepositoryInterface $users
) {}

Use when: You might change data sources, want testability.

Strategy Pattern

Swappable algorithms:

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

class StripeGateway implements PaymentGateway { }
class PayPalGateway implements PaymentGateway { }

class PaymentProcessor
{
    public function __construct(
        private PaymentGateway $gateway
    ) {}

    public function process(Order $order): void
    {
        $this->gateway->charge($order->total);
    }
}

Use when: Multiple ways to do something, runtime switching.

Factory Pattern

Object creation logic:

class NotificationFactory
{
    public static function create(string $type): Notification
    {
        return match($type) {
            'email' => new EmailNotification(),
            'sms' => new SmsNotification(),
            'push' => new PushNotification(),
            default => throw new InvalidArgumentException(),
        };
    }
}

Use when: Complex object creation, many similar objects.

Observer Pattern

React to events:

// Laravel events are observers
class OrderPlaced { }

class SendConfirmation
{
    public function handle(OrderPlaced $event) { }
}

class UpdateInventory
{
    public function handle(OrderPlaced $event) { }
}

Use when: Multiple reactions to one action, decoupling.

Don't Overuse

Patterns add complexity. Use them when:

  • The problem is clear
  • Simpler solutions don't work
  • The team understands the pattern

About the Author

matt

I build and ship automation-driven products using Laravel and modern frontend stacks (Vue/React), with a focus on scalability, measurable outcomes, and tight user experience. I’m based in Toronto, have 13+ years in PHP, and I also hold a pilot’s license. I enjoy working on new tech projects and generally exploring new technology.