Il builder fa parte dei design pattern creazionali, vediamo come implementarlo correttamente in PHP partendo dalla definizione data dalla Gang of Four (GoF).

Il Builder pattern separa la costruzione di un oggetto complesso dalla sua rappresentazione, così che il processo di costruzione possa creare rappresentazioni diverse.

Il design pattern Builder è un pattern creazionale che viene utilizzato per creare oggetti complessi step by step. Il suo obiettivo principale è quello di separare la costruzione di un oggetto complesso dalla sua rappresentazione, in modo che lo stesso processo di costruzione possa essere utilizzato per creare oggetti differenti.

Il pattern Builder prevede l’utilizzo dei seguenti elementi:

  • Oggetto Builder che viene utilizzato per definire le caratteristiche generali e comuni di oggetti omogenei.
  • Metodi di “costruzione” che permettono di definire nello specifico l’oggetto finale passo dopo passo.

Scenari di utilizzo

Il pattern Builder può essere utilizzato ovunque ci sia la necessità di creare oggetti complessi in modo flessibile e modulare, e dove i passaggi di costruzione possono essere suddivisi in metodi più piccoli e gestibili.

Esempi concreti di impiego possono essere:

  • Creazione di oggetti Model: Il pattern Builder può essere utilizzato per creare oggetti Model complessi passo dopo passo. Ad esempio, se si vuole creare un oggetto Model che rappresenta un Ordine con molti dettagli, il pattern Builder può semplificare il processo di creazione dell’oggetto suddividendo i passaggi in metodi più piccoli e gestibili.
  • Costruzione di Query: Il pattern Builder può essere utilizzato per costruire query SQL complesse in modo flessibile e modulare.
  • Creazione di oggetti View: Il pattern Builder può essere utilizzato per creare oggetti View complessi passo dopo passo.

Esempio di pattern Builder in PHP

Vediamo ora un esempio di codice in PHP che utilizza il pattern Builder per creare una classe che funga da query builder SQL.

class QueryBuilder {
  private $table;
  private $fields = array();
  private $conditions = array();

  public function table($table) {
    $this->table = $table;
    return $this;
  }

  public function select($fields) {
    $this->fields = $fields;
    return $this;
  }

  public function where($field, $operator, $value) {
    $this->conditions[] = array(
      'field' => $field,
      'operator' => $operator,
      'value' => $value
    );
    return $this;
  }

  public function build() {
    $query = 'SELECT ' . implode(', ', $this->fields) . ' FROM ' . $this->table;
    if (!empty($this->conditions)) {
      $query .= ' WHERE ';
      foreach ($this->conditions as $condition) {
        $query .= $condition['field'] . ' ' . $condition['operator'] . ' ' . $condition['value'] . ' AND ';
      }
      $query = rtrim($query, ' AND ');
    }
    return $query;
  }
}

In questo esempio, la classe QueryBuilder definisce i metodi per creare una query SQL complessa passo dopo passo. Il metodo table imposta la tabella su cui effettuare la query, il metodo select imposta i campi da selezionare, e il metodo where aggiunge una condizione alla clausola WHERE della query. Infine, il metodo build restituisce la query SQL completa.

Vediamo ora come utilizzare il query builder appena creato:

$query = (new QueryBuilder())
          ->table('products')
          ->select(array('id', 'name', 'price'))
          ->where('price', '>', 10)
          ->where('category', '=', 'electronics')
          ->build();
echo $query;
// Output: SELECT id, name, price FROM products WHERE price > 10 AND category = 'electronics'

Nell’esempio di utilizzo, si crea un oggetto QueryBuilder e si chiamano i metodi necessari per costruire la query desiderata, ovvero selezionare l’id, il nome e il prezzo dei prodotti con un prezzo maggiore di 10 e appartenenti alla categoria ‘electronics’. Infine, si chiama il metodo build per ottenere la query SQL completa.

Vantaggi del design pattern builder

  • Consente di creare oggetti complessi step by step, separando la costruzione dell’oggetto dalla sua rappresentazione e facilitando il processo di creazione.
  • Permette di creare oggetti con diverse configurazioni, utilizzando gli stessi passaggi di costruzione.
  • Consente di creare oggetti in modo più flessibile e modulare, aggiungendo o rimuovendo passaggi di costruzione a seconda delle necessità.
  • Consente di migliorare la leggibilità del codice, in particolare quando si hanno molti parametri da passare al costruttore.

Svantaggi del design pattern builder

  • Può aumentare la complessità del codice, in particolare se si hanno molti passaggi di costruzione da definire.
  • Può richiedere l’implementazione di molte classi aggiuntive (interfacce e classi concrete).
  • Può introdurre un costo aggiuntivo di tempo di esecuzione a causa dell’utilizzo di oggetti intermedi durante il processo di costruzione.

Conclusioni

Il pattern Builder è un pattern molto utile e flessibile per la creazione di oggetti complessi, ma deve essere utilizzato con cautela e valutando attentamente le specifiche esigenze del progetto.

Per un panoramica generale sui design pattern consiglio di leggere l’articolo introduttivo sui design patterns.