Wzorzec Null Object

Wzorzec Null Object pozwala w niektórych sytuacjach wykorzystać polimorfizm do ominięcia sprawdzeń czy obiekt istnieje – if(object != null) then….

Przykład 1 – obsługa strzałek w grze

Załóżmy, że mamy grę w której jest postać którą możemy się poruszać w lewo, prawo, do góry i w dół:

interface Control {
    void moveLeft(Figure figure);
    void moveRight(Figure figure);
    void moveUp(Figure figure);
    void moveDown(Figure figure);
}

I przykładowo mamy implementację standardowego poruszania:

class NormalControl {
    void moveLeft(Figure figure){ figure.setX(figure.getX()-1)};
    void moveRight(Figure figure){ figure.setX(figure.getX()+1)};
    void moveUp(Figure figure){ figure.setY(figure.getY()+1)};
    void moveDown(Figure figure){ figure.setY(figure.getY()-1)};
}

Wzorzec Null Object

I powiedzmy, że taki gracz może po złapaniu jakiegoś artefaktu zostać „zamrożony” (nie może się ruszać) na jakiś określony czas. Aby zaimplementować brak ruchu można wykorzystać wzorzec Null Object (zamiast ustawiać wartości null):

class NoMovingControl {
    void moveLeft(Figure figure){};
    void moveRight(Figure figure){};
    void moveUp(Figure figure){};
    void moveDown(Figure figure){};
}

Przykład 2 – przechodzenie po drzewie

Załóżmy, że mamy hierarchię pracowników w firmie (patrz od lewej do prawej):

User1 ->  User 2 -> User 5
      ->  User 3 -> User 6
      ->  User 4 -> User 7
                 -> User 8

W takim drzewie można wyróżnić dwa rodzaje użytkowników:
-posiadający podwładnych – obiekt złożony
-nie posiadających podwładnych – obiekt liść
Przykładowo można by założyć taki wspólny interfejs:

class User {
    String name;
    Iterator<User> children;
}

I teraz implementacja dla obiektu złożonego User 4:

User user4 = new User("User 4", [user7, user8]);

Wzorzec Null Object

W implementacji obiektu liścia można wykorzystać wzorzec Null Object zamiast ustawiać wartość null dla pola children to tworzymy NullIterator (User 8):

NullIterator implements Iterator<User> {
    boolean hasNext(){ return false };
    User next(){ throw new UnsupportedOperationException(); };
}

User user8 = new User("User 8", new NullIterator());

Warto zajrzeć

1. https://www.youtube.com/watch?v=rQ7BzfRz7OY