Builder – Wzorce Projektowe

Builder to kreacyjny wzorzec projektowy, czyli taki pomagający nam w tworzeniu obiektów. A dokładniej, przydaje się wtedy kiedy tworząc obiekty przez konstruktor zastanawiamy już się czy nadal programujemy czy już piszemy powieść. Wtedy kiedy klas ma wiele właściwości a w szczególności opcjonalnych Builder zwiększa znacząco czytelność kodu i poprawia komfort pracy.

Spójrzmy na przykład prostej klasy User wraz z konstruktorem

class User {
  private username: string;
  private email: string;
  private phoneNumber?: string;
  private avatar?: string;

  constructor(username: string, email: string, phoneNumber?: string, avatar?: string) {
    this.username = username;
    this.email = email;
    this.phoneNumber = phoneNumber;
    this.avatar = avatar;
  }
}

Tak będziemy tworzyć nowe obiekty

class User {
  private username: string;
  private email: string;
  private phoneNumber?: string;
  private avatar?: string;

  constructor(username: string, email: string, phoneNumber?: string, avatar?: string) {
    this.username = username;
    this.email = email;
    this.phoneNumber = phoneNumber;
    this.avatar = avatar;
  }
}

Teraz możecie powiedzieć, że przecież wszsytko wygląda normalnie. Wyobraźcie sobie, że klasa ma 10, 15 zmiennych i musicie sprawdzać, że 3 parametr w konstruktorze to imię a 7 to adres.

No dobra to spójrzmy na trochę bardziej złożoną klasę UserBuilder

class UserBuilder {
  private username: string;
  private email: string;
  private phoneNumber?: string;
  private avatar?: string;

  constructor(username: string, email: string) {
    this.username = username;
    this.email = email;
  }

  setPhoneNumber(phoneNumber: string): UserBuilder {
    this.phoneNumber = phoneNumber;
    return this;
  }

  setAvatar(avatar: string): UserBuilder {
    this.avatar = avatar;
    return this;
  }

  build(): User {
    return new User(this.username, this.email, this.phoneNumber, this.avatar);
  }
}

A tak korzystamy z Buildera do tworzenia obiektów (phoneNumber nie jest ustawiany)

const userFromBuilder: User = new UserBuilder('testUser2', 'userFromBuilder@email.com')
 .setAvatar('avatar')
 .build();

Myślę, że warto tu podkreślić 3 rzeczy:

  1. Konstruktor zawiera tylko wymagane zmienne (może być pusty).
  2. Wszystkie metody ‘set’ zwracają obiekt Buildera. Dzięki temu możemy po kolei ustawić wszystkie oczekiwane własności.
  3. Obiekt User powstaje dobiero na końcu po wywołaniu metody build().