CodeBlanks Logo Icon CodeBlanks

Summary - Design patterns

PHP course · Advanced · Lesson 87/92

Build a cart system with payment method selection using Singleton, Factory and Strategy.

Summary - Cart system

In this summary we combine four patterns in a cart system. Singleton guarantees a single cart instance; Factory creates the payment method; Strategy decides how the payment runs; Builder assembles the items in the cart with fluent methods.

Each pattern carries its own responsibility, achieving separation of concerns. First you will build the cart with Builder, then process the payment with Singleton + Factory + Strategy.

The Builder pattern: fluent setter

The Builder pattern constructs a complex object step by step. Each builder method (for example addItem, setPayment) sets one part of the object and returns $this, so calls chain together.

The final build method returns the finished object. This keeps classes with many constructor parameters readable: add items, set payment, then call build for the result.

Exercise Build the cart fluently with Builder

Write a Builder class. The addItem(string $name, int $price) and setPayment(string $payment) methods return $this. The build method sums the item prices and returns ['total' => $total]. Build the cart with addItem('bread', 10), addItem('milk', 20), setPayment('card') and print the total value.

Show example solution
Write class Builder; addItem and setPayment return self (return $this;). build sums item prices and returns an array. Build with (new Builder())->addItem('bread', 10)->addItem('milk', 20)->setPayment('card')->build().
Example solution:
<?php
class Builder {
    private array $items = [];
    private string $payment = '';
    public function addItem(string $name, int $price): self {
        $this->items[] = ['name' => $name, 'price' => $price];
        return $this;
    }
    public function setPayment(string $payment): self {
        $this->payment = $payment;
        return $this;
    }
    public function build(): array {
        $total = 0;
        foreach ($this->items as $i) { $total += $i['price']; }
        return ['items' => $this->items, 'payment' => $this->payment, 'total' => $total];
    }
}
$cart = (new Builder())
    ->addItem('bread', 10)
    ->addItem('milk', 20)
    ->setPayment('card')
    ->build();
echo 'total: ' . $cart['total'];

Exercise Payment with Singleton + Factory + Strategy

Write an Algorithm interface (with a pay(int $amount): string method). CardStrategy returns 'paid: ' . $amount. Write a Factory class whose createProduct('card') returns a CardStrategy instance. Write a Singleton class whose getInstance returns the single instance and whose checkout(int $amount, Algorithm $algo) method returns $algo->pay($amount). Get the cart, create the card strategy, pay with checkout(30, $pay) and print the result.

Show example solution
string; }. CardStrategy pay returns 'paid: ' . $amount. Factory::createProduct('card') returns CardStrategy. Singleton::getInstance() returns the single instance; checkout(30, $pay) returns $algo->pay($amount).
Example solution:
<?php
interface Algorithm {
    public function pay(int $amount): string;
}
class CardStrategy implements Algorithm {
    public function pay(int $amount): string { return 'paid: ' . $amount; }
}
class Factory {
    public static function createProduct(string $type): Algorithm {
        return match ($type) {
            'card' => new CardStrategy(),
            default => throw new \InvalidArgumentException('unknown'),
        };
    }
}
class Singleton {
    private static ?Singleton $instance = null;
    private function __construct() {}
    public static function getInstance(): Singleton {
        return self::$instance ??= new Singleton();
    }
    public function checkout(int $amount, Algorithm $algo): string {
        return $algo->pay($amount);
    }
}
$cart = Singleton::getInstance();
$pay = Factory::createProduct('card');
echo $cart->checkout(30, $pay);

Test yourself

  1. Which pattern guarantees a single instance in the cart?

    • Strategy
    • Factory
    • Builder
    • Singleton
    Show answer

    Singleton — Correct. Singleton guarantees a single instance; it fits the cart.

  2. Match the cart patterns

    Singleton
    single cart
    Factory
    creates payment method
    Strategy
    payment algorithm
    Builder
    fluent assembler

All lessons in Advanced