Pattern creazionali: Factory, Builder, Singleton
Gestite in modo ordinato la creazione degli oggetti con i pattern creazionali.
Pattern creazionali: Factory, Builder, Singleton è una lezione PHP Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento PHP Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso PHP Academy include 4 lezioni in totale.
Controllare la creazione
I pattern creazionali separano ciò di cui ha bisogno da come viene costruito. Quando la costruzione è condizionale, prevede più passaggi o deve essere centralizzata, disseminare new nel codice crea un accoppiamento tra i chiamanti e le classi concrete. Qui esamineremo Factory (e Factory Method), Builder per l'assemblaggio di oggetti complessi e Singleton, con le relative controindicazioni.
Simple Factory
Una simple factory centralizza una decisione di creazione dietro un unico metodo. I chiamanti richiedono un tipo logico e ricevono un'istanza concreta configurata, senza conoscere i nomi delle classi.
<?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;
Factory Method
Il pattern Factory Method delega l'istanziazione alle sottoclassi. La classe base definisce un algoritmo che chiama un create() astratto; ogni sottoclasse decide quale prodotto concreto creare. È in linea con l'OCP: consente di aggiungere un nuovo creator senza modificare quelli esistenti.
<?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;
Abstract Factory
Una Abstract Factory produce famiglie di oggetti correlati che devono essere usati insieme, ad esempio una coppia MySqlConnection + MySqlQueryBuilder. Garantisce la compatibilità tra le parti perché una sola factory fornisce l'intero insieme. La utilizzi quando una famiglia di prodotti deve rimanere internamente coerente.
Builder: il problema
Quando un oggetto richiede molti parametri opzionali, i costruttori si trasformano in liste di argomenti posizionali illeggibili oppure in overload a cascata, che PHP non supporta nemmeno. Il pattern Builder assembla un oggetto complesso passo dopo passo e alla fine restituisce un prodotto completo e valido.
Fluent Builder
Un fluent builder restituisce $this da ogni setter, quindi build() produce il risultato immutabile. In questo modo il prodotto rimane semplice e la logica di assemblaggio viene spostata nel builder.
<?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;
Builder o costruttori nominati
Nei casi più semplici, gli argomenti nominati di PHP 8 e i costruttori nominati (metodi factory statici) sono spesso preferibili a un builder completo.
- Utilizzi gli argomenti nominati quando tutti i dati sono disponibili contemporaneamente.
- Utilizzi un builder quando l'assemblaggio prevede più passaggi, è condizionale o viene riutilizzato in più punti del codice.
<?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
Un Singleton garantisce un'unica istanza con un punto di accesso globale. Lo implementi con un costruttore privato e un accessor statico. È davvero utile per elementi che devono essere unici all'interno di un processo, ma è anche il pattern più abusato.
<?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
Perché Singleton crea problemi
I Singleton introducono stato globale nascosto: i chiamanti accedono a Config::instance() invece di dichiarare la dipendenza, compromettendo la testabilità e l'esecuzione parallela. Nel PHP moderno, preferisca registrare un'unica istanza condivisa in un container DI con un ciclo di vita «istanza singola» e la inietti. Otterrà un'unica istanza senza l'accoppiamento globale.
Scegliere lo strumento giusto
- Simple Factory/Factory Method: nascondere le classi concrete dietro una decisione di creazione.
- Abstract Factory: produrre famiglie di prodotti compatibili.
- Builder: assemblare oggetti complessi passo dopo passo.
- Singleton: ultima risorsa; preferire servizi condivisi gestiti dal container.
Tutti e quattro riducono l'accoppiamento ai costruttori concreti, rendendo il codice più semplice da estendere e testare.
Factory basata su un registro
Una factory più dinamica cerca i creator in un registro, così i nuovi tipi possono registrarsi autonomamente senza modificare la factory, rispettando davvero l'OCP. È il meccanismo alla base dei sistemi di plugin e dei serializzatori che risolvono un nome di tipo nel relativo costruttore a runtime.
<?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
Verifica rapida
Scelga lo strumento creazionale più adatto allo scenario.
Riepilogo
Ha controllato la creazione degli oggetti con i pattern creazionali: le factory nascondono i tipi concreti e scelgono le famiglie di prodotti, i builder assemblano fluentemente gli oggetti complessi e Singleton offre una soluzione con specifici compromessi. La conclusione moderna è questa: utilizzi liberamente factory e builder, ma sostituisca Singleton con il ciclo di vita di un'istanza condivisa in un container DI, così le dipendenze restano esplicite e testabili.
Domande Frequenti
La lezione «Pattern creazionali: Factory, Builder, Singleton» è gratuita?
Sì — il testo completo di «Pattern creazionali: Factory, Builder, Singleton» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso PHP Academy, passa a CoddyKit PRO. Il corso PHP Academy include 4 lezioni in totale.
Cosa imparerò in «Pattern creazionali: Factory, Builder, Singleton»?
Gestite in modo ordinato la creazione degli oggetti con i pattern creazionali. Eserciti PHP Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare PHP Academy?
Non è richiesta alcuna esperienza precedente. PHP Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.
Quanto tempo richiede la lezione «Pattern creazionali: Factory, Builder, Singleton»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione PHP Academy?
Sì. Ogni lezione PHP Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- I principi SOLID nella pratica
- Pattern creazionali: Factory, Builder, Singleton
- Pattern strutturali: Adapter, Decorator, Facade
- Pattern comportamentali: Strategy, Observer, Command