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.

Null Object

Typ: Czynnościowy

Wzorzec polega na utworzeniu obiektu implementującego konkretny interfejs, jednak nie posiadającego żadnego zachowania. Wszystkie metody wymagane przez interfejs zwracają pusty wynik lub niezmodyfikowane argumenty i nie wykonują żadnych operacji.

Przykładowa implementacja

interface Strategy
{
    public function doSomething();
}

final class NullStrategy implements Strategy
{
    public function doSomething() 
    {
    }
}

Kiedy używać

Wzorzec znajduje zastosowanie w przypadkach kiedy implementacja danego interfejsu jest wymagana, jednak samo zachowanie nie jest istotne, lub kiedy implementacja interfejsu reprezentuje konkretną strategię. Wzorzec z powodzeniem można zastosować w celu wyeliminowania konieczności tworzenia argumentów opcjonalnych. Bardzo dobrze sprawdza się w środowiskach testowych.
Może również posłużyć do rozpoznawania stanu, przykładowo jeżeli encja wymaga identyfikatora nadawanego przez zewnętrzną usługę (np. bazę danych). Podczas inicjalizacji można zastosować NullID tak aby w czasie mapowania encji do bazy danych dało się odróżnić, które encje mają już odpowiadający im rekord w bazie oraz dla których taki rekord należałoby utworzyć.

Przykład użycia

Specyfikacja

  • należy utworzyć usługę odpowiadającą za wysyłkę wiadomości.
  • usługa powinna zapisywać w logach inforamcję o tym, że wiadomość jest przygotowana do wysyłki oraz o tym, została poprawnie wysłana.
  • w środowisku testowym usługa nie powinna zapisywać niczego do logów.

Implementacja

interface Logger
{
    public function log($message);
}

final class NullLogger implements Logger
{
    public function log($message)
    {
    }
}

class MessageSenderService
{
    private $logger;

    public function __construct(Logger $logger)
    {
        $this->logger = $logger;
    }

    public function send(Message $message)
    {
        $this->logger("Pre send message: %d", $message->getId());
        // send message 
        $this->logger("Post send message: %d", $message->getId());
    }
}

Omówienie

Powyższy przypadek można było również zrealizować za pomocą warunków oczekując opcjonalnego argumentu w konstruktorze MessageSenderService. Takie podejście spowodowałoby jednak konieczność utworzenia warunku sprawdzającego czy Logger został przekazany w każdym miejscu, w którym powinien być użyty lub utworzenie prywatnej metody.
Dzięki implementacji NullLogger nie było to konieczne, co przełożyło się na uproszczenie kodu usługi. W prostym przypadku przekazanie jednego opcjonalnego argumentu nie jest jeszcze problemem, jednak kiedy tego typu argumentów przybywa, kod klasy zwiększa się niepotrzebnie.

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.