Czy oddekorowalne decoratory to antywzorzec?

0

Wszyscy wiedzą jak działają decoratory - dodają logikę w runtime'ie.

Moje pytanie brzmi - czy kawałek kodu który wymaga żeby element który dostaje był nieudekorowany to antywzorzec?

Przykład:

interface Base {
    int realMethod();

    Base undecorate();
}
class BaseImpl implements Base {
  public int realMethod() {
    return 2;
  }

  public Base undecorate() {
    return this;
  }
}
class BaseDecorator implements Base {
    private final Base base;

    public BaseDecorator(Base base) {
        this.base = base;
    }

    public int realMethod() {
      return super.realMethod() + 14;
    }

    Base undecorate() {
      return base.undecorate();
    }
}

Teraz gdy ktoś ma Base to to może być albo udekorowane, albo nie. Jednak gdy wywoła Base.undecorate() wtedy na pewno dostanie implementację BaseImpl. Można by nawet jeszcze bardziej przywiązać tą implementację projektując sygnaturę o tak: BaseImpl undecorate();.

Pytanie jednak, czy jeśli moja architektura wymaga jednego miejsca w kodzie gdzie muszę mieć nieudekorowaną instację - to czy to znaczy że zwaliłem?

0

to czy to znaczy że zwaliłem?

Może tak, może nie - jesteś w stanie opisać Twój przypadek konkretniej?

0

Jest REST Api, do którego piszę clienta. API to niestety jest dosyć niekonsystentne i często trzeba robić dwa/trzy requesty po jakieś dane. Wymyśliłem sobie, że "schowam" to api pod jednym sensownym interfejsem które będzie ładowało odpowiednie modele. To API będzie też odpowiedzialne za ładowanie dodatkowych requestów.

Jest teraz dużo klas które korzystają z tego interfejsu. Wprowadzam teraz filtrowanie tego API, Mam dwa wybory:

  • Albo przepisać każdy kawałek kodu który korzysta z interfejsu
  • Udekorować obiekty implementujące ten interfejs, tak by zwracał już przefiltrowane dane (tak że kawałki kodu które z niego korzystają nawet nie wiedzą czy pracują na przefiltrowanych danych czy nie) - i to mi się podoba.

Tutaj jest problem:

  • Jest jeden kawałek kodu który zwraca ilość modeli. Ta ilość wcześniej wyliczana była przez ładowanie wszystkich modeli i liczenie ich (API z którego korzystam nie pozwala na zwrócenie ilości).
  • Teraz ten kawałek kodu, on myśli że te recordy które liczy to jest wszystko, ale przez mój decorator one mogą być pofiltrowane i wtedy policzy tylko wynikową ilosć - a ja chcę wszystkie.
  • To znaczy że implementację którą dostanie tej jeden kawał nie może być udekorowana.
0

Wymyśliłem sobie więc że zamiast przekazywać w zależnościach:

  • Base base - wszystkie lub pofiltrowane
  • BaseImpl - na pewno wszystkie

to przekażę w dół tylko:

  • Base base - wszystkie lub pofiltrowane

i jak ten jeden kawałek kodu będzie chciał nie pofiltrowane, to zrobi sobie Base.undecorate().

0

@lubie_programowac: Tak, sorry my bad. Jasne że super.realMethod() nie może być. Powinno być base.realMethod().

0

Tylko własnie nie wiem czy to jest antywzorzec. Bo można sobie wyobrazić że jeszcze zamiast filtrowania, dojdzie np decorator który coś mapuje, i wtedy interfejs miałby mieć dwie metody?
undecorateFilter() i undecorateMap()? Dopóki jest jeden decorator to sie wydaje sensowne - ale czy jest sensowne? Nie wiem :/

0

Zamiast mieć undecorate() możesz też po prostu przekazywać obydwie instancje klienta do tej klasy filtrującej (jedną udekorowaną - drugą nie).

Wydaje mi się to lepsze niż zabawa w undecorate(), ponieważ:

  • nie będziesz musiał tej metody tworzyć ani opisywać (less is better),
  • będziesz mógł nazwać tych klientów sensownie w parametrach konstruktora oraz polach klasy (np. clientAdapter i filteredClientAdapter czy coś w ten deseń).
0
Patryk27 napisał(a):
  • będziesz mógł nazwać tych klientów sensownie w parametrach konstruktora oraz polach klasy (np. clientAdapter i filteredClientAdapter czy coś w ten deseń).

No nie za bardzo bo filteredClientAdapter wcale nie musi być udekorowany.

0

Nic strasznego się nie stanie IMO jeśli w jakiejś sytuacji wyjdzie, że clientAdapter == filteredClientAdapter.

0

Miałem na myśli nazwę zmiennej. Że filtered nie musi być udecorowany, więc czemu ma się nazywać filtered.

0

Tak, rozumiem - ponieważ może być udekorowany i czasem będzie (w tych sytuacjach, gdy filtrowanie będzie aktywne).
IMO jest to koniec końców prostsze w wytłumaczeniu niż undecorate().

1 użytkowników online, w tym zalogowanych: 0, gości: 1