Warstwa Abstrakcji - stanowi izolację pomiędzy kodem programisty a zewnętrznymi modułami, pozwala odseparować system od jego zależności przez co czyni go podatnym na zmiany i aktualizacje. Przywiązując system do innej usługi czynimy go słabym.

Factory Method

Typ: Kreacyjny

Wzorzec projektowy, którego celem jest dostarczenie interfejsu dla klas odpowiedzialnych za tworzenie konkretnego typu obiektów.

Przykładowa implementacja

interface Factory
{
    public function createFrom(array $arguments);
}

class ObjectFactory implements Factory
{
    public function createFrom(array $arguments)
    {
        return new Object($arguments['foo'], $arguments['bar']);
    }
}

Kiedy używać

Wzorzec świetnie sprawdza się w sytuacjach, w których należy utworzyć obiekt posiadający pewien predefiniowany zestaw zachowań (implementuje interfejs), których oczekujemy, jednak sam typ obiektu nie jest istotny.

Przykład użycia

Specyfikacja

  • należy utworzyć usługę, która na podstawie przekazanych parametrów stworzy obiekt użytkownika.
  • w systemie mogą istnieć dwa typy użytkowników, osoba prywatna oraz firma.
  • firma musi posiadać NIP, osoba prywatna musi posiadać PESEL.
  • firma nie może być osobną prywatną, ani odwrotnie.

Implementacja

interface User
{
    // user behavior
}

final class PrivatePerson implements User
{
    private $peselNumber;

    public function __construct(PESEL $peselNumber)
    {
        $this->pesel = $peselNumber;
    }
}

final class Company implements User
{
    private $nip;

    public function __construct(NIP $nipNumber)
    {
        $this->nip = $nipNumber;
    }
}

interface UserFactory
{
    public function createFrom(array $data);
}

final class MultipleUserTypeFactory implements UserFactory
{
    public function createFrom(array $data)
    {
        if (array_key_exists('nip', $data) {
            return new Company(new Nip($data['nip']));
        }

        if (array_key_exists('pesel', $data]) {
            return new PrivatePerson(new PESEL($data['pesel']));
        }

        throw new \InvalidArgumentException("Data required to create User needs to have PESEL or NIP.");
    }
}

final class UserRegistrationService
{
    private $userFactory;

    public function __construct(UserFactory $factory)
    {
        $this->userFactory = $factory;
    }

    public function register(array $data)
    {
        $user = $this->userFactory->createFrom($data);
        // do something with user
    }
}

Omówienie

W powyższym przykładzie usługa UserRegistrationService nie dba o to jaki typ użytkownika utworzy, nie takie jest jej przeznaczenie. Dzięki temu usługa może być rozszerzana poprzez przekazanie jej innej implementacji UserFactory bez konieczności modyfikowania kodu samej usługi.
Wzorzec jest również pomocny w przypadku uruchamiania aplikacji w środowisku testowym nie polegającym na żadnej bazie danych. Rodzaj fabryki może być zależny od środowiska, dzięki czemu raz utworzona zostanie encja która w jakiś sposób mapowana jest na bazę danych, a raz encja "czysta", nie będąca powiązana z niczym zewnętrznym.

Powiązane wpisy

Błędy?

Znalazłeś błąd?
Chciałbyś podać lepszy przykład użycia?
A może nie zgadzasz się z implementacją przykładu?

Edytuj na Github.com Popraw lub zgłoś błąd

Pytania

Masz pytania odnośnie omawianego wzorca? Chciałbyś zapytać czy wzorzec pasuje do problemu, który aktualnie rozwiązujesz? Dobrze się składa, to jest idealne miejsce.

Błędy, sugestie ich poprawy, dyskusję na temat poprawności implementacji danego przykładu prosimy prowadzić poprzez Github Issues
Akceptuję

Ten serwis używa plików cookies. Więcej o plikach cookies.