Dekorator vs add(X)

0

Na stronie https://decibel.ni.com/content/docs/DOC-13332 w komentarzach TheMadScientist pyta się czemu lepiej jest użyć dekoratora zamiast zapisu jaki on proponuje. Komentarz niżej Daklu odpowiada, że lepiej jest rozszerzać klasy bez modyfikowania, bo wtedy nie cierpią na tym testy.

Szczerze mówiąc nie łapię o jakim rozszerzaniu tutaj mówi Daklu. Jeśli metoda addCondiment istnieje od samego początku klasy Coffy to poprzez wywoływanie tej metody klasa nie jest modyfikowana, a obiekt - to co innego.

Jak wy uważacie?

0

Ale przecież masz jasno napisane w czym rzecz. Dekorator pozwala rozszerzyć / zmodyfikować funkcjonalność pewnej klasy bez zmiany samej klasy.
Przykład z życia wzięty, lepszy niz ta kawa:
Wyobraź sobie że masz klasę która wykonuje kalibracje pewnych parametrów które dostaje. Tzn klasa dostaje nazwę parametru oraz wartość a następnie wczytuje z bazy danych formułę matematyczną do kalibracji i wykonuje obliczenia. Np.

  • parametr "temperatura" i wartość 10
  • w bazie danych dla tego parametru mamy formułę x^2+3x
  • wczytujemy tą formułę i wyliczamy sobie wartość 130
  • zwracamy wyliczoną wartość
    I to jest klasa która już jest w systemie, jest przetestowana i śmiga jak rącza gazela. Ale przychodzi informacja od klienta że co prawda śmiga dobrze, ale bardzo wolno. Krótka analiza pokazuje że zwykle aplikacja wykonuje kalibracji zaledwie kilku różnych parametrów w czasie uruchomienia, więc wpadasz na pomysł żeby wprowadzić w takim razie cache (bo teraz za każdym razem robimy zapytanie do bazy, nawet jeśli setny raz kalibrujemy temperature)! Ale modyfikowanie istniejącej klasy to zło. Ba, czasem nawet nie możesz tego zrobić. Bo przecież ta klasa może być z jakiejś biblioteki i w ogóle nie możesz jej zmienić.
    W związku z tym robisz dekorator CalibratorWithCache który zawiera w sobie mapę nazwa_parametru->formuła_kalibracji. W swojej aplikacji zamiast standardowego new Calibrator() tworzysz new CalibratorWithCache(new Calibrator()), a "twój" kalibrator zapamiętuje sobie w cache formuły wczytane z bazy i deleguje obliczenia do standardowej implementacji.
    W ten sposób w czasie uruchomienia programu będziesz robił tylko jedno zapytanie do bazy dla jednego parametru.
    Dodatkowy plus tego rozwiazania jest taki że modyfikacja kodu jest tylko w jednym miejscu, tam gdzie tworzysz kalibrator.

Widzisz sens? :)

1

To co @Shalom opisałeś bardziej pasuje chyba do wzorca Proxy.

A co do Dekoratora to może lepszym przykładem byłoby gdybyśmy chcieli klasę która operuje na temperaturze w skali Fahrenheita (CalibratorInFahrenheit). Ponieważ mamy już klasę działającą dla skali Celsjusza to piszemy tylko dekorator który:

  1. zamienia temperature z F na C
  2. używa Calibrator do przeprowadzenia właściwych obliczeń
  3. wynik zamienia na temperature w skali Fahreiheita i zwraca wynik.
0

@Shalom Twoja odpowiedź nie jest odpowiedzią na moje pytanie.

Wiem, że dekorowaniem można sobie rozszerzać zachowanie klasy tak jak to mamy w przypadku strumieni z java.io.

Chciałbym po prostu wiedzieć dlaczego Daklu potępił rozwiązanie w oparciu o metodę add.

Konkretny przykład:

W moim przykładzie powiedzmy, że chciałbym dynamicznie konstruować walidatory ogłoszeń, bo ogłoszenie na każdej ze stron wyróżniać mogą się innymi danymi i innym stopniem ważności.

(Sposób z add)
W takim przypadku postanowiłem, że zrobić N klas walidatorów dziedziczących po JobAdValidator. Potem dla każdej klasy przetwarzającej serwisy będę przekazywał listę walidatorów, a klasa serwisu w pętli odpali kolejno te walidatory.

(Sposób z dekoratorem)
W przypadku, gdybym miał użyć dekoratora zrobiłbym tak - wychodzę od bazowego walidatora, i go dekoruje go kolejnymi walidatorami. Wtedy uzyskuje jeden walidator, który przekazuje do serwisu i ten serwis wywołuje go bez uruchamiania pętli.

Na moje oko oba podejścia są w miarę okej; choć pierwsze bez dekoratora jest moim zdaniem czytelniejsze.

1

@pyjoker nadal cię nie rozumiem. My chyba czytamy dwa różne komentarze. TheMadScientist spytał wyraźnie o sytuację czemu dodanie do coffee listy condimentów i dodanie metody addCondiment jest gorsze od dekoratora a odpowiedź była jasna - żeby nie ruszać istniejącego kodu. Koniec. Kropka.
Jeśli piszesz nowy kod to ta zasada nieobowiązuje. W twoim przypadku dużo sensowniej jest zrobić listę walidatorów a nie jeden ultra walidator ;]

0

Dzięki, nie zwróciłem uwagi, że celem tego artykułu było dodawanie funkcjonalności bez edycji istniejących klas.

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