0Pricing
PHP Academy · Lekcja

Wzorce kreacyjne: Factory, Builder, Singleton

Proszę uporządkować tworzenie obiektów za pomocą wzorców kreacyjnych.

Wzorce kreacyjne: Factory, Builder, Singleton to bezpłatna lekcja PHP Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej PHP Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs PHP Academy zawiera 4 lekcji w sumie.

Kontrolowanie tworzenia

Wzorce kreacyjne oddzielają to, czego potrzebujesz, od sposobu, w jaki jest to budowane. Gdy tworzenie zależy od warunków, przebiega wieloetapowo lub musi być scentralizowane, rozproszenie new w bazie kodu uzależnia kod wywołujący od konkretnych klas. W tej części omówimy fabrykę (i metodę wytwórczą), budowniczego do złożonego składania obiektów oraz Singleton wraz z jego ograniczeniami.

Prosta fabryka

Prosta fabryka centralizuje decyzję dotyczącą tworzenia za pomocą jednej metody. Kod wywołujący prosi o typ logiczny i otrzymuje skonfigurowaną instancję konkretnej klasy, nie znając jej nazwy.

<?php
interface Notifier { public function send(string $msg): string; }
final class EmailNotifier implements Notifier {
    public function send(string $m): string { return "email: $m"; }
}
final class SmsNotifier implements Notifier {
    public function send(string $m): string { return "sms: $m"; }
}

final class NotifierFactory {
    public static function make(string $channel): Notifier {
        return match ($channel) {
            'email' => new EmailNotifier(),
            'sms'   => new SmsNotifier(),
            default => throw new InvalidArgumentException($channel),
        };
    }
}
echo NotifierFactory::make('sms')->send('Hi'), PHP_EOL;

Metoda wytwórcza

Wzorzec Metoda wytwórcza odracza tworzenie instancji do podklas. Klasa bazowa definiuje algorytm, który wywołuje abstrakcyjne create(); każda podklasa wybiera konkretny produkt. Jest to rozwiązanie zgodne z OCP: można dodać nowego twórcę bez modyfikowania istniejących.

<?php
abstract class ReportExporter {
    abstract protected function create(): string;
    public function export(): string {
        return 'Exported as ' . $this->create();
    }
}
final class PdfExporter extends ReportExporter {
    protected function create(): string { return 'PDF'; }
}
final class CsvExporter extends ReportExporter {
    protected function create(): string { return 'CSV'; }
}
echo (new PdfExporter())->export(), PHP_EOL;
echo (new CsvExporter())->export(), PHP_EOL;

Fabryka abstrakcyjna

Fabryka abstrakcyjna tworzy rodziny powiązanych obiektów, które muszą być używane razem (np. MySqlConnection + MySqlQueryBuilder). Gwarantuje zgodność elementów, ponieważ jedna fabryka dostarcza cały zestaw. Należy jej używać, gdy rodzina produktów musi pozostać wewnętrznie spójna.

Budowniczy: problem

Gdy obiekt wymaga wielu opcjonalnych parametrów, konstruktory przeradzają się w nieczytelne listy argumentów pozycyjnych albo w konstruktorów teleskopowych, których PHP nawet nie obsługuje. Wzorzec Budowniczy składa złożony obiekt krok po kroku, zwracając na końcu gotowy, poprawny produkt.

Budowniczy z płynnym interfejsem

Budowniczy z płynnym interfejsem zwraca $this z każdej metody ustawiającej, a następnie build() tworzy niezmienny wynik. Dzięki temu sam produkt pozostaje prosty, a logika składania zostaje przeniesiona do budowniczego.

<?php
final class Query {
    public function __construct(public readonly string $sql) {}
}
final class QueryBuilder {
    private string $table = '';
    private array $where = [];
    public function from(string $t): self { $this->table = $t; return $this; }
    public function where(string $c): self { $this->where[] = $c; return $this; }
    public function build(): Query {
        $sql = "SELECT * FROM {$this->table}";
        if ($this->where) { $sql .= ' WHERE ' . implode(' AND ', $this->where); }
        return new Query($sql);
    }
}
echo (new QueryBuilder())->from('users')->where('age > 18')->build()->sql, PHP_EOL;

Budowniczy a nazwane konstruktory

W prostszych przypadkach nazwane argumenty PHP 8 oraz nazwane konstruktory (statyczne metody fabrykujące) często sprawdzają się lepiej niż pełny budowniczy.

  • Argumentów nazwanych należy używać, gdy wszystkie dane są dostępne jednocześnie.
  • Budowniczego należy używać, gdy składanie przebiega wieloetapowo, zależy od warunków lub jest wykorzystywane w wielu miejscach wywołań.
<?php
final class Money {
    private function __construct(public readonly int $cents, public readonly string $cur) {}
    public static function fromDollars(float $d): self {
        return new self((int) round($d * 100), 'USD');
    }
    public static function zero(string $cur = 'USD'): self {
        return new self(0, $cur);
    }
}
var_dump(Money::fromDollars(19.99)->cents); // int(1999)

Singleton

Singleton gwarantuje istnienie jednej instancji i zapewnia globalny punkt dostępu. Należy go zaimplementować za pomocą prywatnego konstruktora i statycznego akcesora. Jest naprawdę przydatny w przypadku elementów, które rzeczywiście muszą być unikatowe w obrębie procesu, ale jest również najbardziej nadużywanym wzorcem.

<?php
final class Config {
    private static ?self $instance = null;
    private array $data = ['debug' => true];
    private function __construct() {}
    public static function instance(): self {
        return self::$instance ??= new self();
    }
    public function get(string $k): mixed { return $this->data[$k] ?? null; }
}
var_dump(Config::instance()->get('debug'));
var_dump(Config::instance() === Config::instance()); // true

Dlaczego Singleton szkodzi

Singletony wprowadzają ukryty stan globalny: kod wywołujący korzysta z Config::instance() zamiast deklarować zależność, co utrudnia testowanie i wykonywanie równoległe. We współczesnym PHP należy zamiast tego zarejestrować jedną współdzieloną instancję w kontenerze DI (cykl życia „pojedyncza instancja”) i wstrzykiwać ją. Otrzymuje się jedną instancję bez globalnego powiązania.

Wybór właściwego narzędzia

  • Prosta fabryka/metoda wytwórcza: ukrywa konkretne klasy za decyzją dotyczącą tworzenia.
  • Fabryka abstrakcyjna: tworzy zgodne ze sobą rodziny produktów.
  • Budowniczy: składa złożone obiekty krok po kroku.
  • Singleton: ostateczność; należy preferować współdzielone usługi zarządzane przez kontener.

Wszystkie cztery wzorce zmniejszają powiązanie z konkretnymi konstruktorami, dzięki czemu kod łatwiej rozszerzać i testować.

Fabryka oparta na rejestrze

Bardziej dynamiczna fabryka wyszukuje twórców w rejestrze, dzięki czemu nowe typy rejestrują się samodzielnie bez modyfikowania fabryki (prawdziwa zgodność z OCP). Tak działają systemy wtyczek i serializatory, które w czasie działania odwzorowują nazwę typu na konstruktor.

<?php
interface Shape { public function name(): string; }
final class Circle implements Shape { public function name(): string { return 'circle'; } }
final class Square implements Shape { public function name(): string { return 'square'; } }

final class ShapeRegistry {
    private array $creators = [];
    public function register(string $key, callable $factory): void {
        $this->creators[$key] = $factory;
    }
    public function create(string $key): Shape {
        return ($this->creators[$key] ?? throw new InvalidArgumentException($key))();
    }
}
$r = new ShapeRegistry();
$r->register('circle', fn() => new Circle());
$r->register('square', fn() => new Square());
echo $r->create('square')->name(), PHP_EOL; // square

Szybki test

Należy wybrać najlepsze narzędzie kreacyjne dla danego scenariusza.

Podsumowanie

Kontrolowano tworzenie obiektów za pomocą wzorców kreacyjnych: fabryk do ukrywania konkretnych typów i wybierania rodzin produktów, budowniczych do płynnego składania złożonych obiektów oraz Singletona wraz z jego kompromisami. Współczesny wniosek jest następujący: fabryki i budowniczowie są dobrym wyborem, natomiast Singletona należy zastępować cyklem życia współdzielonej instancji w kontenerze DI, aby zachować jawne i testowalne zależności.

Często zadawane pytania

Czy lekcja „Wzorce kreacyjne: Factory, Builder, Singleton” jest bezpłatna?

Tak — pełny tekst „Wzorce kreacyjne: Factory, Builder, Singleton” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu PHP Academy, przejdź na CoddyKit PRO. Kurs PHP Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Wzorce kreacyjne: Factory, Builder, Singleton”?

Proszę uporządkować tworzenie obiektów za pomocą wzorców kreacyjnych. Ćwiczysz PHP Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć PHP Academy?

Nie wymagamy żadnego doświadczenia. PHP Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Wzorce kreacyjne: Factory, Builder, Singleton”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji PHP Academy?

Tak. Każda lekcja PHP Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Zasady SOLID w praktyce
  2. Wzorce kreacyjne: Factory, Builder, Singleton
  3. Wzorce strukturalne: Adapter, Decorator, Facade
  4. Wzorce behawioralne: Strategy, Observer, Command
← Powrót do PHP Academy