Dekorator vs add(X)

PY
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 10 lat
  • Postów:12
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?

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
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? :)


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 2x, ostatnio: Shalom
KN
  • Rejestracja:około 13 lat
  • Ostatnio:11 miesięcy
  • Postów:7
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.
edytowany 1x, ostatnio: knrdk
Shalom
Czemu proxy? Interfejs zostaje ten sam. Nie staramy sie tu robić żadnej fasady, nie ukrywamy puli obiektów ani żadnej dziwnej skomplikowanej logiki komunikacji z faktycznym obiektem. Robimy tylko prosty wrapper i dodajemy funkcjonalność ;]
KN
Po prostu moim zdaniem w twoim rozwiązaniu ograniczamy dostęp do pewnej zasobożernej operacji a nie rozszerzamy funkcjonalność obiektu i to bardziej pasuje do idei wzorca Proxy. Ale nie zamierzam się o to spierać ;)
Shalom
@knrdk przeciez nie ograniczyliśmy dostępu do funkcjonalności, tylko dodaliśmy funkcjonalność proxy ;] Zauważ że taki BufferedReader w javie to jest dekorator a jedyne co robi to ogranicza kosztowną operacja czytania z pliku poprzez czytanie większymi blokami :)
PY
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 10 lat
  • Postów:12
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.

edytowany 2x, ostatnio: pyjoker
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
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 ;]


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
PY
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 10 lat
  • Postów:12
0

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

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)