Ist "StringBuilder" eine Anwendung des Builder-Entwurfsmusters?

31

Beschränkt sich das Muster "Builder" auf die Adressierung des Anti-Musters "Teleskopkonstruktor", oder kann es auch auf das allgemeinere Problem der komplizierten Erstellung unveränderlicher Objekte angewendet werden?

Die StringBuilderKlasse hat das Wort "Builder" im Namen, hat jedoch nichts mit Teleskopkonstruktoren zu tun. Sie hilft uns lediglich dabei, alle Daten zu sammeln, die wir zum Konstruktor eines unveränderlichen Objekts weitergeben müssen.

Für mich scheint die Antwort ein sehr klares "Ja" zu sein, aber es scheint einige Meinungsverschiedenheiten bezüglich des Themas zu geben, und ich hatte gehofft, dass jemand es vielleicht klären könnte.

Ich beantwortete diese Frage: Programmierer SE: Legitime "echte Arbeit" in einem Konstruktor? Wo das OP ein (vermutlich unveränderliches) Objekt erstellen möchte, das einen komplexen Baum enthält, und die Idee des "Builder" -Musters auftauchte, fand ich während der Recherche dieses Q & A, das zu sagen scheint, dass der "StringBuilder" -Stil der Objekterstellung ist nicht eine Anwendung des Musters „Builder“, aus Gründen , die mir nicht klar sind: Stackoverflow - Stringbuilder und Builder - Muster . (Diejenigen, die diese Frage beantworteten, konnten, soweit ich das beurteilen kann, nicht überzeugen.)

Mike Nakis
quelle
2
Ich finde Paul Sasiks Antwort auf diese Stapelüberlauf-Frage völlig überzeugend: StringBuilder ist eine "Problemumgehung" für das Leistungsproblem der Verkettung unveränderlicher Zeichenfolgen, nicht mehr. Bestenfalls wird StringBuilder "leider benannt". Sie könnten das Argument vorbringen, dass StringBuilder Webseiten "erstellen" kann, aber das ist eine spezifische Anwendung eines allgemeinen Mechanismus.
Robert Harvey
3
Paul Sasiks Antwort für Java ist falsch - ich habe mir den zugrunde liegenden Quellcode angesehen. StringBuilderscheint ein zugrunde liegendes Zeichenarray zu verwenden, um den String darzustellen, und ermöglicht es Ihnen, Dinge wie Einfügungen und Entfernungen an jedem Punkt durchzuführen. Letztendlich denke ich, dass StringBuilder eine Problemumgehung für unveränderliche String-Objekte ist, aber es sieht für mich ansonsten so aus, als würde es die Absicht des Builder-Musters erfüllen.
Thomas Owens
4
Ich muss viel mehr darüber nachdenken - es stört mich. Fast hätte ich geschrieben, warum so etwas wie StringBuilder eine Version des Builder-Musters ist und alle anderen sich geirrt haben. Aber ich fand ein paar Schwächen, war überzeugt, dass ich mich geirrt hatte, und schaffte es dann, zu meinem ersten Gedanken zurückzukehren. Wenn Sie sich nur die Absicht des Builder-Musters ansehen, können Sie leicht erkennen, dass "StringBuilder ein Builder ist". Wenn Sie sich die Struktur des Builder-Musters ansehen, ist es schwieriger.
Thomas Owens
1
Für das, was es wert ist, stimmt diese Antwort auf Stack Overflow mit meinem anfänglichen Gedanken überein, dass StringBuilder eine Builder-Implementierung ist und die Kommentare interessant sind. Sie können also beide Seiten des Arguments finden. Ich bevorzuge diese Frage - ich weiß nicht, ob ich eine gute Antwort finden kann, aber es ist mit Sicherheit eine interessante Frage. Ich werde darüber nachdenken.
Thomas Owens
2
Nicht alle GoF-Muster haben sich bewährt. Ich bin nicht sayin , ich bin gerade sayin'.
Ben

Antworten:

36

A StringBuilderähnelt dem Builder-Muster, teilt jedoch nicht viel mit der GoF-Beschreibung dieses Entwurfsmusters. Der ursprüngliche Punkt des Entwurfsmusters war

Trennen Sie die Konstruktion eines komplexen Objekts von seiner Darstellung, damit derselbe Konstruktionsprozess unterschiedliche Darstellungen erstellen kann.

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

(Hinweis: "komplex" bedeutet in erster Linie "aus mehreren Teilen zusammengesetzt", nicht unbedingt "kompliziert" oder "schwierig")

Die "verschiedenen Darstellungen" ist hier der Schlüssel. ZB unter der Annahme dieses Konstruktionsprozesses:

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 ...");
}

Es kann vorkommen, dass wir am Ende ein HtmlDocumentoder ein TexDocumentoder ein haben, MarkdownDocumentje nachdem, welche konkrete Implementierung bereitgestellt wird:

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

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

Ein zentraler Punkt des Builder-Musters ist also der Polymorphismus . Das Design Patterns-Buch vergleicht dieses Muster mit der Abstract Factory:

Abstract Factory ähnelt dem Builder, da es auch komplexe Objekte erstellen kann. Der Hauptunterschied besteht darin, dass sich das Builder-Muster auf die schrittweise Erstellung eines komplexen Objekts konzentriert. […] Builder gibt das Produkt als letzten Schritt zurück, aber was die abstrakte Fabrik betrifft, wird das Produkt sofort zurückgegeben.

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

Dieser schrittweise Aspekt ist dann zum populäreren Aspekt des Builder-Musters geworden, so dass das Builder-Muster im allgemeinen Sprachgebrauch so verstanden wird:

Teilen Sie die Konstruktion eines Objekts in mehrere Schritte auf. Auf diese Weise können wir benannte Argumente oder optionale Parameter auch in Sprachen verwenden, die diese Funktionen nicht unterstützen.

Wikipedia definiert das Muster folgendermaßen:

Das Builder-Muster ist ein Entwurfsmuster für eine Objekterstellungssoftware. Im Gegensatz zur Abstrakte Fabrik und das Factory - Methode Muster , deren Absicht ist Polymorphismus zu ermöglichen, ist die Absicht des Erbauers Musters ist eine Lösung für das Teleskop - Konstruktor anti-Muster zu finden [Bearbeiten] . […]

Das Builder-Muster hat einen weiteren Vorteil. Es kann für Objekte verwendet werden, die flache Daten enthalten (HTML-Code, SQL-Abfrage, X.509-Zertifikat ...), dh Daten, die nicht einfach bearbeitet werden können. Diese Art von Daten kann nicht schrittweise bearbeitet werden und muss sofort bearbeitet werden. Die beste Methode zum Erstellen eines solchen Objekts ist die Verwendung einer Builder-Klasse. [Zitat benötigt]

- aus Builder Pattern auf Wikipedia , von verschiedenen Mitwirkenden.

Wie wir sehen können, gibt es kein wirklich gemeinsames Verständnis, auf welches Muster sich dieser Name bezieht, und in einigen Punkten widersprechen sich sogar unterschiedliche Definitionen (z. B. hinsichtlich der Relevanz des Polymorphismus für Bauherren).

Die einzige gemeinsame Eigenschaft von StringBuildermit verschiedenen Interpretationen des Musters ist, dass das Produkt Schritt für Schritt und nicht in einem Zug erstellt wird. Die GoF-Definition des Entwurfsmusters wird nicht streng gelesen. Beachten Sie jedoch, dass es sich bei Entwurfsmustern um formbare Konzepte handelt, die die Kommunikation erleichtern sollen. Ich würde weiterhin StringBuilderein Beispiel für das Builder-Muster nennen, wenn auch ein atypisches - der Hauptgrund für diese Struktur in Java ist eine performante Verkettung bei unveränderlichen Zeichenfolgen, aber kein interessantes objektorientiertes Design.

amon
quelle
7
Es scheint mir, dass das Erstellen unveränderlicher Objekte eine der gebräuchlichsten Verwendungen von Buildern zu sein scheint. Ich denke, dies hat die von GoF beschriebene primäre Verwendung ersetzt. Stimmen Sie also zu, dass dies definitiv am besten als eine Instanz des Musters beschrieben werden kann.
Jules
Stimmen Sie der Verwendung beim Erstellen unveränderlicher Diagramme zu. Ein weiteres Anwendungsbeispiel für Builder-DSLs ist sehr nützlich, um während Unit + Integrationstests große Diagramme von falschen Daten / ObjectMothers zu erstellen.
StuartLC