Czy „StringBuilder” jest aplikacją wzorca projektowego Builder?

31

Czy wzorzec „Konstruktora” ogranicza się do rozwiązania anty-wzorca „konstruktora teleskopowego”, czy też można powiedzieć, że dotyczy również bardziej ogólnego problemu skomplikowanego tworzenia niezmiennych obiektów?

StringBuilderKlasy ma słowo „budowniczy” w nazwie, ale to nie ma nic, teleskopowe do czynienia z konstruktorów, to po prostu pomaga nam zebrać wszystkie dane, które musimy przekazać do konstruktora obiektu niezmiennej.

Wydaje mi się, że odpowiedź jest bardzo wyraźnym „tak”, ale wydaje się, że istnieje pewna różnica zdań na ten temat, więc miałem nadzieję, że ktoś może to wyjaśnić.

Odpowiedziałem na to pytanie: programiści SE: Uzasadniona „prawdziwa praca” w konstruktorze? gdzie OP chce stworzyć (przypuszczalnie niezmienny) obiekt zawierający złożone drzewo, a pojawił się pomysł wzorca „konstruktora”, a podczas badania go znalazłem pytania i odpowiedzi, które wydają się wskazywać, że styl tworzenia obiektów „StringBuilder” jest nie zastosowanie wzorca „Builder” z powodów, które nie są dla mnie jasne: Stackoverflow - StringBuilder i Builder Pattern . (Ci, którzy odpowiedzieli na to pytanie, nie przedstawili przekonującego argumentu, o ile mogę powiedzieć.)

Mike Nakis
źródło
2
Uważam, że odpowiedź Paula Sasika na to pytanie dotyczące przepełnienia stosu jest całkowicie przekonująca: StringBuilder to „obejście” problemu wydajnościowego łączenia niezmiennych ciągów, nic więcej. W najlepszym wypadku StringBuilder ma „niestety nazwę”. Można wysunąć argument, że StringBuilder może „budować” strony internetowe, jak sądzę, ale jest to specyficzne zastosowanie ogólnego mechanizmu.
Robert Harvey,
3
Odpowiedź Paula Sasika jest zła dla Javy - spojrzałem na kod źródłowy. StringBuilderwygląda na to, że używa podstawowej tablicy znaków do reprezentowania Ciągu i umożliwia wykonywanie czynności takich jak wstawianie i usuwanie w dowolnym momencie. Ostatecznie myślę, że StringBuilder jest obejściem dla niezmiennych obiektów String, ale poza tym wygląda mi na to, że spełnia założenia wzorca Builder.
Thomas Owens
4
Muszę o tym więcej myśleć - przeszkadza mi to. Prawie zacząłem pisać, dlaczego coś takiego jak StringBuilder jest wersją wzorca Buildera i wszyscy inni się mylili. Ale znalazłem kilka słabości, przekonałem się, że się mylę, ale potem udało mi się wrócić do mojej pierwszej myśli. Jeśli spojrzysz na samą intencję wzorca Konstruktora, łatwo zauważyć, że „StringBuilder jest Konstruktorem”. Jeśli spojrzysz na strukturę wzorca Konstruktora, jest trudniej.
Thomas Owens
1
Jeśli chodzi o wartość, ta odpowiedź na temat przepełnienia stosu zgadza się z moją początkową myślą, że StringBuilder jest implementacją konstruktora, a komentarze są interesujące. Możesz więc znaleźć obie strony argumentu. Opowiadam się za tym pytaniem - nie wiem, czy potrafię ułożyć dobrą odpowiedź, ale na pewno jest to interesujące pytanie. Zastanowię się nad tym.
Thomas Owens
2
Nie wszystkie wzorce GoF wytrzymują próbę czasu. Ja nie mówię , ja tylko mówię.
Ben,

Odpowiedzi:

36

A StringBuilderjest podobny do Wzorca Konstruktora, ale niewiele dzieli z opisem GoF tego wzorca projektowego. Pierwotnym punktem wzoru projektowego było

Oddziel konstrukcję złożonego obiektu od jego reprezentacji, aby ten sam proces budowy mógł tworzyć różne reprezentacje.

- od Design Patterns , Gamma, Helm, Johnson, Vlissides.

(uwaga: „złożony” oznacza przede wszystkim „złożony z wielu części”, niekoniecznie „skomplikowany” lub „trudny”)

Kluczowe są tutaj „różne reprezentacje”. Np. Zakładając ten proces budowy:

interface ArticleBuilder {
  void addTitle(String title);
  void addParagraph(String paragraph);
}

void createArticle(ArticeBuilder articleBuilder) {
  articleBuilder.addTitle("Is String Builder an application of ...");
  articleBuilder.addParagraph("Is the Builder Pattern restricted...");
  articleBuilder.addParagraph("The StringBuilder class ...");
}

możemy skończyć na a HtmlDocumentlub a TexDocumentlub w MarkdownDocumentzależności od tego, jakie konkretne wdrożenie jest zapewnione:

class HtmlDocumentBuilder implements ArticleBuilder {
  ...
  HtmlDocument getResult();
}

HtmlDocumentBuilder b = new HtmlDocumentBuilder();
createArticle(b);
HtmlDocument dom = b.getResult();

Tak więc jednym centralnym punktem wzoru Konstruktora jest polimorfizm . Książka Wzory wzorów porównuje ten wzór z Fabryką abstrakcyjną:

Fabryka abstrakcyjna jest podobna do Konstruktora, ponieważ również może konstruować złożone obiekty. Podstawowa różnica polega na tym, że wzorzec Konstruktora koncentruje się na konstruowaniu złożonego obiektu krok po kroku. […] Konstruktor zwraca produkt jako ostatni krok, ale jeśli chodzi o fabrykę abstrakcyjną, produkt jest natychmiast zwracany.

- od Design Patterns , Gamma, Helm, Johnson, Vlissides.

Ten aspekt krok po kroku stał się bardziej popularnym aspektem wzorca konstruktora, dzięki czemu we wspólnej mowie wzorzec konstruktora jest rozumiany w następujący sposób:

Podziel konstrukcję obiektu na wiele kroków. To pozwala nam używać nazwanych argumentów lub parametrów opcjonalnych nawet w językach, które nie obsługują tych funkcji.

Wikipedia definiuje następujący wzór:

Wzorzec konstruktora to wzorzec projektowy oprogramowania do tworzenia obiektów. W przeciwieństwie do abstrakcyjnego wzorca fabrycznego i wzorca metody fabrycznej, którego celem jest umożliwienie polimorfizmu, intencją wzorca konstruktora jest znalezienie rozwiązania anty-wzorca teleskopowego konstruktora [potrzebne źródło] . […]

Wzorzec konstruktora ma jeszcze jedną zaletę. Można go używać do obiektów zawierających dane płaskie (kod HTML, zapytanie SQL, certyfikat X.509 ...), to znaczy dane, których nie można łatwo edytować. Tego typu danych nie można edytować krok po kroku i należy je edytować od razu. Najlepszym sposobem na zbudowanie takiego obiektu jest użycie klasy konstruktora. [wymagany cytat]

- z Builder Pattern na Wikipedii , przez różnych autorów.

Jak widzimy, nie ma naprawdę powszechnego zrozumienia, do którego wzorca odnosi się ta nazwa, aw niektórych punktach różne definicje nawet są ze sobą sprzeczne (np. Odnośnie znaczenia polimorfizmu dla Konstruktorów).

Jedyną wspólną właściwością StringBuilderróżnych interpretacji wzoru jest to, że produkt jest tworzony krok po kroku, a nie za jednym razem. Nie spełnia surowej interpretacji definicji wzoru projektowego GoF, ale należy pamiętać, że wzorce projektowe są koncepcjami plastycznymi mającymi na celu ułatwienie komunikacji. Nadal będę nazywał StringBuilderprzykład Wzorca Konstruktora, choć nietypowego - głównym powodem tej struktury w Javie jest wydajna konkatenacja w obecności niezmiennych ciągów, ale nie jakiś interesujący projekt obiektowy.

amon
źródło
7
Wydaje mi się, że tworzenie niezmiennych obiektów wydaje się być jednym z bardziej powszechnych zastosowań Konstruktorów - myślę, że zastąpiło to podstawowe użycie opisane przez GoF, więc zgódź się, że zdecydowanie najlepiej jest to opisać jako przykład wzorca.
Jules
Zgadzam się z wykorzystaniem do tworzenia niezmiennych wykresów, Kolejny przypadek użycia dla DSL Buildera jest naprawdę przydatny do tworzenia dużych wykresów Fałszywych danych / ObjectMothers podczas testów Unit + Integration.
StuartLC,