{"id":21036,"date":"2016-09-15T11:45:01","date_gmt":"2016-09-15T10:45:01","guid":{"rendered":"https:\/\/www.inovex.de\/?p=2156"},"modified":"2022-12-01T11:59:50","modified_gmt":"2022-12-01T10:59:50","slug":"das-builder-pattern-teil-2","status":"publish","type":"post","link":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/","title":{"rendered":"Das Builder Pattern [Teil 2]"},"content":{"rendered":"<p>Im <a href=\"https:\/\/www.inovex.de\/das-builder-pattern-teil-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">ersten Teil<\/a> dieser Artikelserie wurden das <em>Builder Pattern<\/em> selbst und ein paar typische Anwendungsf\u00e4lle beschrieben. Nun stelle ich hier einige Varianten f\u00fcr die Implementierung eines <em>Builders<\/em> und seiner einzelnen Funktionsaspekte vor. Manche davon wurden bereits kurz angesprochen und sollen jetzt genauer erl\u00e4utert werden. Es wird jeweils mit einem kleinen Beispiel dargestellt, wie der <em>Builder<\/em> verwendet wird und welche Implementierung das erm\u00f6glicht.<!--more--><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\"><\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Method-Chaining\" >Method-Chaining<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Test-DSL\" >Test-DSL<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Kaskadierung\" >Kaskadierung<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Pflichtfelder\" >Pflichtfelder<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Sammeln-der-Attributwerte-und-Erzeugen-der-Instanz\" >Sammeln der Attributwerte und Erzeugen der Instanz<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Erzeugung-unabhaengiger-Instanzen\" >Erzeugung unabh\u00e4ngiger Instanzen<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Interne-Kontainer-Instanz\" >Interne Kontainer-Instanz<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Setzen-der-Attributwerte\" >Setzen der Attributwerte<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Platzierung-des-Builder\" >Platzierung des Builder<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Unabhaengiger-Builder\" >Unabh\u00e4ngiger Builder<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Benachbarter-Builder\" >Benachbarter Builder<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Innerer-Builder\" >Innerer Builder<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#Empfehlungen\" >Empfehlungen<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Method-Chaining\"><\/span>Method-Chaining<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Ein Hauptgrund f\u00fcr die komfortable Verwendbarkeit des <em>Builders<\/em> ist der Einsatz von <a href=\"https:\/\/en.wikipedia.org\/wiki\/Method_chaining\" target=\"_blank\" rel=\"noopener noreferrer\">Method Chaining<\/a>. Dabei liefern die Mutatoren jeweils wieder die Referenz auf den <em>Builder<\/em> zur\u00fcck, wodurch sich mit einer Verkettung von Aufrufen die Spezifikation und Erzeugung der <em>Product<\/em>-Instanz im Quelltext sehr gut lesbar und nachvollziehbar darstellen l\u00e4sst. Da hier immer dieselbe <em>Builder<\/em>-Instanz zur\u00fcckgeliefert wird, stellt diese Art von Method-Chaining eine Umsetzung des Fluent Interface ohne Grammatik dar. In <a href=\"https:\/\/www.inovex.de\/named-parameters-java-fluent-interfaces\/\" target=\"_blank\" rel=\"noopener noreferrer\">einem fr\u00fcheren Artikel<\/a> beschreibe ich weiterf\u00fchrende M\u00f6glichkeiten, einen <em>Builder<\/em> mit Fluent Interface nutzbringend einzusetzen.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Test-DSL\"><\/span>Test-DSL<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Gerade die Lesbarkeit von Code ist in Testklassen von zentraler Bedeutung, damit die Tests einen Mehrwert als Anforderungsbeschreibung f\u00fcr den Produktiv-Code haben. In <a href=\"https:\/\/www.amazon.de\/Clean-Code-Handbook-Software-Craftsmanship\/dp\/0132350882\" target=\"_blank\" rel=\"noopener noreferrer\">Clean Code<\/a> wird empfohlen, die technische Implementierung von Datenaufbau und Ergebnispr\u00fcfung durch entsprechend benannte Hilfsmethoden u.\u00e4. hinter einer DSL (Domain Specific Language) zu verbergen. Der Einsatz eines Fluent Interface im <em>Builder<\/em> und der Einsatz von Factory-Methoden f\u00fcr <em>Builder<\/em>-Instanzen mit vorbef\u00fcllten Standardwerten bieten hierf\u00fcr optimale Voraussetzungen.<\/p>\n<pre class=\"lang:java decode:true\" title=\"DSL f\u00fcr die Vorbereitung von Testdaten\">@Test\r\n\r\npublic void stepPropagatesResultToItems() {\r\n\r\n  step.process(aProcessData()\t\t\/\/ static import of ProcessData.aProcessData\r\n\r\n    .withParentProcessId(17L)\t\t\/\/ method chaining\r\n\r\n    .withPropagateResults(true)\r\n\r\n    .withStep(\"activate\")\r\n\r\n    .withUserId(0L)\r\n\r\n    .withOffset(23)\r\n\r\n    .build());\t\t\t\t\/\/ creation method\r\n\r\n  verify(itemRepository).update(itemCaptor.capture());\r\n\r\n  assertProcessResult(itemCaptor.getValue());\r\n\r\n}\r\n\r\n<\/pre>\n<pre class=\"lang:java decode:true\" title=\"Ein Builder mit Fluent Interface und Factory-Methode\">public class ProcessData {\r\n\r\n  private Long parentProcessId;\r\n\r\n  public void setParentProcessId(Long parentProcessId) {\r\n\r\n    this.parentProcessId = parentProcessId;\r\n\r\n  }\r\n\r\n  [...]\r\n\r\n  public static Builder aProcessData() {\t\/\/ create Builder instance\r\n\r\n    return new Builder();\r\n\r\n  }\r\n\r\n  public static class Builder {\r\n\r\n    private Long parentProcessId;\r\n\r\n    public ProcessData build() {\r\n\r\n      ProcessData result = new ProcessData();\r\n\r\n      result.setParentProcessId(this.parentProcessId);\r\n\r\n      [...]\r\n\r\n      return result;\t\t\t\/\/ return ProcessData instance\r\n\r\n    }\r\n\r\n    public Builder withParentProcessId(Long parentProcessId) {\r\n\r\n      this.parentProcessId = parentProcessId;\r\n\r\n      return this;\t\t\t\/\/ return Builder instance in every mutator of the builder\r\n\r\n    }\r\n\r\n    [...]\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<h3><span class=\"ez-toc-section\" id=\"Kaskadierung\"><\/span>Kaskadierung<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Das deklarative Erstellen von Testdaten gibt dem Leser eines Testfalls einen guten \u00dcberblick, mit welcher Eingabe die getestete Funktion gerade aufgerufen wird.<\/p>\n<p>Gerade beim Erstellen von hierarchischen Objektstrukturen bietet die Verwendung eines Fluent Interface f\u00fcr die beteiligten <em>Builder<\/em> den Vorteil, die Struktur der Daten beim Aufbau klar sichtbar zu machen. Dabei kann die Mutator-Methode der aggregierenden Klasse (hier z.B. <code>withItems()<\/code>) wahlweise ein <code>Item<\/code>-Objekt oder auch ein <code>Item.Builder<\/code>-Objekt akzeptieren, welches dann intern erst zu einem <code>Item<\/code> aufgel\u00f6st wird.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Kaskadierende Verwendung von Builder Klassen\">@Test\r\n\r\npublic void stepPropagatesResultToItems() {\r\n\r\n  step.process(aProcessData()\r\n\r\n    .withParentProcessId(17L)\r\n\r\n    .withPropagateResults(true)\r\n\r\n    .withStep(\"activate\")\r\n\r\n    .withUserId(0L)\r\n\r\n    .withOffset(23)\r\n\r\n    .withItems(\r\n\r\n      anItem()\r\n\r\n        .withId(23L)\r\n\r\n        .withName(\"first item\")\r\n\r\n        .build(),\t\t\t\t\t\/\/ insert Item instance\r\n\r\n      anItem()\r\n\r\n        .withId(24L)\r\n\r\n        .withName(\"second item\"))\t\/\/ insert Item.Builder instance\r\n\r\n    .build());\r\n\r\n  verify(itemRepository).update(itemCaptor.capture());\r\n\r\n  assertItemsYieldProcessResult(itemCaptor.getValue());\r\n\r\n}\r\n\r\n<\/pre>\n<pre class=\"lang:java decode:true\" title=\"Ein Builder wird im anderen Builder benutzt\">public class ProcessData {\r\n\r\n  private List items;\r\n\r\n  public void setItems(List items) {\r\n\r\n    this.items = items;\r\n\r\n  }\r\n\r\n  [...]\r\n\r\n  public static Builder aProcessData() {\t\/\/ create Builder instance\r\n\r\n    return new Builder();\r\n\r\n  }\r\n\r\n  public static class Builder {\r\n\r\n    private List items = new ArrayList&lt;&gt;();\r\n\r\n    public ProcessData build() {\r\n\r\n      ProcessData result = new ProcessData();\r\n\r\n      result.setItems(this.items);\r\n\r\n      [...]\r\n\r\n      return result;\t\t\t\t\t\t\/\/ return ProcessData instance\r\n\r\n    }\r\n\r\n    public Builder withItem(Item item) {\r\n\r\n      this.items.add(item);\t\t\t\t\t\/\/ add Item instance\r\n\r\n      return this;\r\n\r\n    }\r\n\r\n    public Builder withItem(Item.Builder itemBuilder) {\r\n\r\n      this.items.add(itemBuilder.build());\t\/\/ add created Item instance\r\n\r\n      return this;\r\n\r\n    }\r\n\r\n    [...]\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<p>Es ist nat\u00fcrlich auch m\u00f6glich, die Erzeugung der Items bis zum Aufruf der <code>build()<\/code>-Methode des <code>ProcessData.Builder<\/code> zu verz\u00f6gern, wenn man vorher die <code>Item.Builder<\/code> intern ansammelt. Gerade wenn f\u00fcr singul\u00e4re Attribute <em>Builder<\/em>-Instanzen akzeptiert wurden, w\u00fcrde dann nur vom zuletzt gesetzten <em>Builder<\/em> ein Objekt erzeugt.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Mutator wird mehrmals aufgerufen\">  ProcessDataBuilder builder = aProcessData();\r\n\r\n  builder.withRecord(aRecord().withId(15L));\t\/\/ this builder will never be called\r\n\r\n  [...]\r\n\r\n  builder.withRecord(aRecord().withId(17L));\r\n\r\n  ProcessData = builder.build();\t\t\t\t\/\/ will call the second recordBuilder\r\n\r\n<\/pre>\n<pre class=\"lang:java decode:true\" title=\"Nur der letzte Builder wird aufgerufen\">public class ProcessData {\r\n\r\n  private Record record;\r\n\r\n  public void setRecord(Record record) {\r\n\r\n    this.record = record;\r\n\r\n  }\r\n\r\n  [...]\r\n\r\n  public static Builder aProcessData() {\t\t\/\/ create Builder instance\r\n\r\n    return new Builder();\r\n\r\n  }\r\n\r\n  public static class Builder {\r\n\r\n    private Record.Builder recordBuilder;\r\n\r\n    public ProcessData build() {\r\n\r\n      ProcessData result = new ProcessData();\r\n\r\n      if(this.recordBuilder != null) {\r\n\r\n        \/\/ only create Record instance if there is a builder\r\n\r\n        result.setRecord(this.recordBuilder.build());\r\n\r\n      }\r\n\r\n      [...]\r\n\r\n      return result;\t\t\t\t\t\t\t\/\/ return ProcessData instance\r\n\r\n    }\r\n\r\n    public Builder withRecord(Record.Builder recordBuilder) {\r\n\r\n      this.recordBuilder = recordBuilder;\t\t\/\/ save builder instance\r\n\r\n      return this;\r\n\r\n    }\r\n\r\n    [...]\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"Pflichtfelder\"><\/span>Pflichtfelder<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Die Verwendung eines <em>Builders<\/em> ist besonders hilfreich, wenn das <em>Product<\/em> viele optionale Attribute hat. Aber auch die Pflichtfelder m\u00fcssen ad\u00e4quat behandelt werden. Je nach den fachlichen Anforderungen kann es sinnvoll sein, einen leeren <em>Builder<\/em> zu erzeugen und im Laufe von mehreren Prozessen die notwendigen Attributwerte anzusammeln. Vor der Erzeugung des <em>Product<\/em> sollte dann die Vollst\u00e4ndigkeit und Konsistenz validiert werden.<\/p>\n<p>Ist es aber leicht m\u00f6glich, zun\u00e4chst alle Pflichtfeldwerte zu bestimmen, so liegt es nahe, diese auch f\u00fcr die Erzeugung des <em>Builders<\/em> bereits verpflichtend einzufordern. Dieser ist danach sofort in der Lage, valide <em>Product<\/em>-Instanzen zu erzeugen, kann aber vorher noch mit optionalen Werten angereichert werden.<\/p>\n<p>Sollen statische Factory-Methoden zur Erzeugung von <em>Builder<\/em>-Instanzen benutzt werden, um die Lesbarkeit zu erh\u00f6hen, m\u00fcssen die Pflichtfelder darin entsprechend durchgereicht werden. Gegebenenfalls sollte der Methodenname dann darauf hinweisen, f\u00fcr welche Attribute die Werte bestimmt sind, was bei Verwendung des <em>Builder<\/em>-Konstruktors wiederum nicht m\u00f6glich w\u00e4re.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Builder mit Pflichtfeld\">public class Item {\r\n\r\n  private final long id;\r\n\r\n  private Item(long id) {\r\n\r\n    this.id = id;\r\n\r\n  }\r\n\r\n  [...]\r\n\r\n  public static Builder anItemWithId(long id) {\r\n\r\n    return new Builder(id);\r\n\r\n  }\r\n\r\n  public static class Builder {\r\n\r\n    private final long id;\r\n\r\n    public Build(long id) {\r\n\r\n      this.id = id;\r\n\r\n    }\r\n\r\n    public Item build() {\r\n\r\n      Item item = new Item(id);\r\n\r\n      [...]\r\n\r\n      return item;\r\n\r\n    }\r\n\r\n    [...]\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<pre class=\"lang:java decode:true\" title=\"Factory-Methode mit Pflichtfeld\">ProcessData data = aProcessData()\r\n\r\n  .withParentProcessId(17L)\r\n\r\n  .withItems(\r\n\r\n    Item.anItemWithId(24L)\t\t\t\/\/ mandatory value for field id\r\n\r\n      .withName(\"first item\"))\r\n\r\n  .build());\r\n\r\n<\/pre>\n<h2><span class=\"ez-toc-section\" id=\"Sammeln-der-Attributwerte-und-Erzeugen-der-Instanz\"><\/span>Sammeln der Attributwerte und Erzeugen der Instanz<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Ein <em>Builder<\/em> hat die Aufgabe, Attributwerte zu sammeln und zu gegebener Zeit mit den aktuell gesetzten Werten eine <em>Product<\/em>-Instanz zu erzeugen. Dies ist intern wieder auf unterschiedliche Weise m\u00f6glich, allerdings sollten dabei die Bedingungen erf\u00fcllt werden, die <a href=\"https:\/\/www.inovex.de\/das-builder-pattern-teil-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">in Teil eins des Artikels im Abschnitt \u201eImplementierung\u201c<\/a> genannt wurden. Insbesondere Punkt 3), die Unabh\u00e4ngigkeit der erzeugten Instanzen, soll mit dem folgenden Beispiel erl\u00e4utert werden.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Erzeugung-unabhaengiger-Instanzen\"><\/span>Erzeugung unabh\u00e4ngiger Instanzen<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"lang:java decode:true\" title=\"Wiederverwendung einer Builder-Instanz\">\/\/ endlessly process jobs from queue\r\n\r\npublic void work() {\r\n\r\n  Item.Builder prototype = Item.anItem()\t\/\/ builder with some common values\r\n\r\n    .withWorkerId(this.workerId)\r\n\r\n    .withOriginType(Origin.CREATED_BY_JOB);\r\n\r\n  while(!this.shutdown) {\r\n\r\n    Job job = this.queue.next();\t\t\t\/\/ blocks until next job is available\r\n\r\n    Item item = prototype\t\t\t\t\t\/\/ reuse builder instance\r\n\r\n      .withCreationDate(DateTime.now())\r\n\r\n      .withJobId(job.getId())\r\n\r\n      .build();\t\t\t\t\t\t\/\/ item instance with some specific values\r\n\r\n    job.run();\r\n\r\n    item.setDuration(job.getDuration());\t\/\/ set value on instance\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<p>W\u00fcrde der <em>Builder<\/em> in seiner <code>build()<\/code>-Methode nicht jedes mal eine neue <code>Item<\/code>-Instanz erzeugen sondern bei jedem Aufruf immer die selbe Instanz zur\u00fcck liefern, an der nur die aktuellen Attribute ge\u00e4ndert wurden, so w\u00fcrde der oben gezeigte Prozess potentiell zu ungewollten Folgen f\u00fchren. Nach mehrmaligem Aufruf von <code>build()<\/code> w\u00e4ren also mehrere Referenzen auf dieselbe <code>Item<\/code>-Instanz in Umlauf. Die Attribute dieser Instanz w\u00fcrden mit jedem Aufruf am Builder durch die letzten gesammelten Attribute \u00fcberschrieben. Au\u00dferdem w\u00fcrden alle Prozesse, die \u00c4nderungen an ihrer <code>Item<\/code>-Instanz vornehmen, diese Werte ebenfalls f\u00fcr alle anderen Prozesse \u00fcberschreiben. Es ist also unbedingt notwendig, bei jedem Aufruf an <code>build()<\/code> eine neue Instanz zu erzeugen, oder auf andere Weise sicherzustellen, dass <code>build()<\/code> nur ein einziges Mal aufgerufen werden kann.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Interne-Kontainer-Instanz\"><\/span>Interne Kontainer-Instanz<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Und tats\u00e4chlich ist es gar nicht so abwegig, schon vor Aufruf der <code>build()<\/code>-Methode die <em>Product<\/em>-Instanz bereits erzeugt zu haben. Denn wie in <a href=\"https:\/\/www.inovex.de\/blog\/das-builder-pattern-teil-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">Teil eins<\/a> abschlie\u00dfend erw\u00e4hnt wird, ist die Duplikation der Attributfelder das gr\u00f6\u00dfte Manko bei der Arbeit mit einem <em>Builder<\/em>. Um in der <em>Builder<\/em>-Klasse nicht jedes Attribut erneut definieren zu m\u00fcssen, kann also einfach eine interne <em>Product<\/em>-Instanz angelegt werden, deren Attribute beim Sammeln am <em>Builder<\/em> direkt gesetzt werden.<\/p>\n<p>Wie im letzten Abschnitt allerdings festgestellt wurde, kann in der <code>build()<\/code>-Methode nicht einfach diese vorhandene Instanz an den Aufrufer herausgegeben werden, weil ja irgendwie eine neue Instanz ins Spiel kommen muss. Und die interne Instanz einfach durch eine neue zu ersetzen w\u00fcrde semantisch zu einem vollst\u00e4ndigen Zur\u00fccksetzen des <em>Builders<\/em> f\u00fchren, was von au\u00dfen nicht erkennbar ist. Es wird also eine Klon-Funktion ben\u00f6tigt, um eine <em>Product<\/em>-Instanz mit ihren Attributwerten zu kopieren.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Builder mit interner Product-Instanz\">public class Builder {\r\n\r\n  private final item = new Item();\t\t\/\/ initialize builder with internal item instance\r\n\r\n  public void withId(Long id) {\r\n\r\n    this.item.setId(id);\t\t\t\t\/\/ set attributes to internal instance\r\n\r\n  }\r\n\r\n  public Item build() {\r\n\r\n    return clone(this.item);\t\t\t\/\/ provide new instance with same attributes\r\n\r\n  }\r\n\r\n  private Item clone(Item original) {\r\n\r\n    [...]\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<p>Wo die Variante mit eigenen Attributen im <em>Builder<\/em> zu Duplikation f\u00fchrt, da entsteht durch die Verwendung einer internen Instanz eine st\u00e4rkere technische Abh\u00e4ngigkeit des <em>Builders<\/em> von der <em>Product<\/em>-Implementierung. Gerade Seiteneffekte bei den Mutatoren f\u00fchren zu Problemen, die Attribute m\u00fcssen f\u00fcr das Klonen sp\u00e4ter wieder unver\u00e4ndert lesbar sein oder es muss au\u00dferhalb eine <code>clone()<\/code>-Methode verf\u00fcgbar sein. Und generell k\u00f6nnen \u00c4nderungen an der <em>Product<\/em>-Klasse leichter zu Funktionsfehlern im <em>Builder<\/em> f\u00fchren. Pers\u00f6nlich w\u00fcrde ich eher die Duplikation der Attribute empfehlen, insbesondere wenn dies automatisiert geschieht.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Setzen-der-Attributwerte\"><\/span>Setzen der Attributwerte<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Unabh\u00e4ngig von der gew\u00e4hlten Variante gibt es immer einen Zeitpunkt, an dem der <em>Builder<\/em> die Attributwerte an der <em>Product<\/em>-Instanz setzt. Auch hier gibt es wieder mehrere Optionen, die gr\u00f6\u00dftenteils von der Implementierung des <em>Product<\/em> und insbesondere der Sichtbarkeit der jeweiligen Felder und Methoden abh\u00e4ngig sind.<\/p>\n<p>Es kann ein Konstruktor verwendet werden, der gegebenenfalls manche oder alle Attribute entgegennimmt. Die Nutzung von Mutator-Methoden, hoffentlich ohne Seiteneffekte, ist sehr g\u00e4ngig und bei entsprechender Sichtbarkeit kann auf die Felder auch direkt zugegriffen werden.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Unterschiedlicher Zugriff auf die Product-Attribute\">public class Builder {\r\n\r\n  private Long id;\r\n\r\n  private String name;\r\n\r\n  private Type type;\r\n\r\n  [...]\r\n\r\n  public Item build() {\r\n\r\n    Item item = new Item(this.id);\r\n\r\n    item.setName(this.name);\r\n\r\n    item.type = this.type;\r\n\r\n    return item;\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<p>Gerade dann, wenn dem <em>Builder<\/em> andere M\u00f6glichkeiten zur Instanziierung er\u00f6ffnet werden sollen als sonstigen Aufrufern, ist die Platzierung der <em>Builder<\/em>-Klasse relativ zum <em>Product<\/em> besonders zu beachten.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Platzierung-des-Builder\"><\/span>Platzierung des <em>Builder<\/em><span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Ein <em>Builder<\/em> wird immer eine starke semantische Abh\u00e4ngigkeit von seinem <em>Product<\/em> aufweisen, immerhin soll er mit der Instanzerzeugung ja einen wesentlichen Teil von dessen Lebenszyklus erbringen bzw. unterst\u00fctzen. Im Mindesten muss er die Klasse erzeugen und alle Attribute verarbeiten k\u00f6nnen, die in seinen Anwendungsf\u00e4llen relevant sind.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Unabhaengiger-Builder\"><\/span>Unabh\u00e4ngiger <em>Builder<\/em><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Die loseste Bindung zwischen den beiden Klassen ergibt sich wohl, wenn ein <em>Builder<\/em> implementiert wird, um komfortabel Instanzen f\u00fcr Tests erzeugen zu k\u00f6nnen. Die <em>Builder<\/em>-Klasse kann daf\u00fcr im Test-Scope in einem beliebigen Package untergebracht werden, solange sie die <em>Product<\/em>-Klasse von dort importieren, instanziieren und initialisieren kann. Bei der Auslieferung des Systems ist der <em>Builder<\/em> dann gar nicht enthalten. Statische Factory-Methoden sollten am <em>Builder<\/em> selbst platziert werden, weil es sonst zu einer zyklischen Abh\u00e4ngigkeit zwischen den beiden Klassen kommt.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Der Builder ist m\u00f6glichst unabh\u00e4ngig vom Product\">public class ItemBuilder {\r\n\r\n  public static ItemBuilder anItem() {\r\n\r\n    return new ItemBuilder();\r\n\r\n  }\r\n\r\n  private Long id;\r\n\r\n  [...]\r\n\r\n  public Item build() {\r\n\r\n    Item item = new Item();\r\n\r\n    item.setId(this.id);\r\n\r\n    return item;\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<h3><span class=\"ez-toc-section\" id=\"Benachbarter-Builder\"><\/span>Benachbarter <em>Builder<\/em><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Allerdings passiert es gerade bei der testgetriebenen Entwicklung nicht selten, dass der <em>Builder<\/em> auch bei der Implementierung der eigentlichen Prozesse ganz n\u00fctzlich erscheint und daher in den Produktions-Scope verschoben wird. Liegen die Klassen an sehr unterschiedlichen Orten, kann es passieren, dass bei \u00c4nderungen des <em>Product<\/em> die Implementierung des <em>Builders<\/em> nicht nachgezogen wird. Daher sollten die Klassen einigerma\u00dfen nahe beieinander untergebracht werden.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Innerer-Builder\"><\/span>Innerer <em>Builder<\/em><span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Soll es aber nur dem <em>Builder<\/em> m\u00f6glich sein, Instanzen des <em>Product<\/em> zu erzeugen oder schreibend auf dessen Attribute zuzugreifen, dann ist der <em>Builder<\/em> als innere Klasse des <em>Product<\/em> zu implementieren. Auf diese Weise k\u00f6nnen unver\u00e4nderliche Klassen komfortabel erzeugt oder sonstige Validit\u00e4tsbedingungen forciert werden. Hierdurch kommt es zu einer wesentlich h\u00f6heren Koh\u00e4sion der beiden Klassen und es k\u00f6nnen unter Umst\u00e4nden auch unn\u00f6tige Mutatoren in der <em>Product<\/em>-Klasse eingespart werden.<\/p>\n<pre class=\"lang:java decode:true\" title=\"Der Builder als innere Klasse des Product\">public class Item {\r\n\r\n  private final long id;\r\n\r\n  private Item(long id) {\t\t\t\/\/ only visible to builder\r\n\r\n    this.id = id;\r\n\r\n  }\r\n\r\n  public static Builder anItem() {\t\/\/ factory on product class\r\n\r\n    return new ItemBuilder();\r\n\r\n  }\r\n\r\n  public static class Builder {\t\t\/\/ inner class\r\n\r\n    private Long id;\r\n\r\n    private void withId(long id) {\t\/\/ force value with primitive\r\n\r\n      this.id = id;\r\n\r\n    }\r\n\r\n    public Item build() throws ValidationException {\r\n\r\n      validate();\r\n\r\n      return new Item(this.id);\t\t\/\/ create valid immutable instance\r\n\r\n    }\r\n\r\n    private void validate() throws ValidationException {\r\n\r\n      if(this.id == null) {\r\n\r\n        throw new ValidationException();\r\n\r\n      }\r\n\r\n    }\r\n\r\n  }\r\n\r\n}\r\n\r\n<\/pre>\n<h3><span class=\"ez-toc-section\" id=\"Empfehlungen\"><\/span>Empfehlungen<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Pers\u00f6nlich finde ich es sinnvoll, den <em>Builder<\/em> als Top-Level Klasse anzulegen, sofern das m\u00f6glich ist. Entweder im selben Package oder in einem <code>.builder<\/code> Subpackage. Wenn er nur in Tests verwendet wird, sollte er auch nur dort sichtbar sein. Nur bei einer notwendigen sehr hohen Bindung ist das nicht m\u00f6glich.<\/p>\n<p>Die Gefahr, dass \u00c4nderungen am <em>Product<\/em> im <em>Builder<\/em> nicht nachvollzogen werden, sch\u00e4tze ich als relativ gering ein. Immerhin soll die neue Funktionalit\u00e4t ja auch benutzt und getestet werden. Und wenn daf\u00fcr dann keine Anpassung im <em>Builder<\/em> n\u00f6tig war, dann war es wohl f\u00fcr die Anwendungsf\u00e4lle des <em>Builders<\/em> im System nicht relevant.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im ersten Teil dieser Artikelserie wurden das Builder Pattern selbst und ein paar typische Anwendungsf\u00e4lle beschrieben. Nun stelle ich hier einige Varianten f\u00fcr die Implementierung eines Builders und seiner einzelnen Funktionsaspekte vor. Manche davon wurden bereits kurz angesprochen und sollen jetzt genauer erl\u00e4utert werden. Es wird jeweils mit einem kleinen Beispiel dargestellt, wie der Builder [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":12718,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"ep_exclude_from_search":false,"footnotes":""},"tags":[68],"service":[425],"coauthors":[{"id":25,"display_name":"Sebastian Schmidt","user_nicename":"sschmidt"}],"class_list":["post-21036","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-backend","service-backend"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Das Builder Pattern [Teil 2] - inovex GmbH<\/title>\n<meta name=\"description\" content=\"Hier stelle ich einige Varianten f\u00fcr die Implementierung eines Builders im Builder Pattern und seiner einzelnen Funktionsaspekte vor.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Das Builder Pattern [Teil 2] - inovex GmbH\" \/>\n<meta property=\"og:description\" content=\"Hier stelle ich einige Varianten f\u00fcr die Implementierung eines Builders im Builder Pattern und seiner einzelnen Funktionsaspekte vor.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/\" \/>\n<meta property=\"og:site_name\" content=\"inovex GmbH\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/inovexde\" \/>\n<meta property=\"article:published_time\" content=\"2016-09-15T10:45:01+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-12-01T10:59:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/builder-pattern.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2300\" \/>\n\t<meta property=\"og:image:height\" content=\"876\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Sebastian Schmidt\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/builder-pattern-1024x390.png\" \/>\n<meta name=\"twitter:creator\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:site\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Sebastian Schmidt\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"11\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Sebastian Schmidt\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/\"},\"author\":{\"name\":\"Sebastian Schmidt\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/a2ffffeaeaa18b9961297ca47e5f3799\"},\"headline\":\"Das Builder Pattern [Teil 2]\",\"datePublished\":\"2016-09-15T10:45:01+00:00\",\"dateModified\":\"2022-12-01T10:59:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/\"},\"wordCount\":1476,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/08\\\/builder-pattern.png\",\"keywords\":[\"Backend\"],\"articleSection\":[\"General\",\"Infrastructure\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/\",\"name\":\"Das Builder Pattern [Teil 2] - inovex GmbH\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/08\\\/builder-pattern.png\",\"datePublished\":\"2016-09-15T10:45:01+00:00\",\"dateModified\":\"2022-12-01T10:59:50+00:00\",\"description\":\"Hier stelle ich einige Varianten f\u00fcr die Implementierung eines Builders im Builder Pattern und seiner einzelnen Funktionsaspekte vor.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/08\\\/builder-pattern.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2016\\\/08\\\/builder-pattern.png\",\"width\":2300,\"height\":876,\"caption\":\"Builder-pattern erkl\u00e4rt anhand von Pizza, Artisckocken und Oliven\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/das-builder-pattern-teil-2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Das Builder Pattern [Teil 2]\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"name\":\"inovex GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\",\"name\":\"inovex GmbH\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"width\":1921,\"height\":1081,\"caption\":\"inovex GmbH\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/inovexde\",\"https:\\\/\\\/x.com\\\/inovexgmbh\",\"https:\\\/\\\/www.instagram.com\\\/inovexlife\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/inovex\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UC7r66GT14hROB_RQsQBAQUQ\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/a2ffffeaeaa18b9961297ca47e5f3799\",\"name\":\"Sebastian Schmidt\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/Avatar_3000-scaled-96x96.jpg5f905a8b3627c2eb15cdb285c29fe6cf\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/Avatar_3000-scaled-96x96.jpg\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/Avatar_3000-scaled-96x96.jpg\",\"caption\":\"Sebastian Schmidt\"},\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/author\\\/sschmidt\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Das Builder Pattern [Teil 2] - inovex GmbH","description":"Hier stelle ich einige Varianten f\u00fcr die Implementierung eines Builders im Builder Pattern und seiner einzelnen Funktionsaspekte vor.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/","og_locale":"de_DE","og_type":"article","og_title":"Das Builder Pattern [Teil 2] - inovex GmbH","og_description":"Hier stelle ich einige Varianten f\u00fcr die Implementierung eines Builders im Builder Pattern und seiner einzelnen Funktionsaspekte vor.","og_url":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/","og_site_name":"inovex GmbH","article_publisher":"https:\/\/www.facebook.com\/inovexde","article_published_time":"2016-09-15T10:45:01+00:00","article_modified_time":"2022-12-01T10:59:50+00:00","og_image":[{"width":2300,"height":876,"url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/builder-pattern.png","type":"image\/png"}],"author":"Sebastian Schmidt","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/builder-pattern-1024x390.png","twitter_creator":"@inovexgmbh","twitter_site":"@inovexgmbh","twitter_misc":{"Verfasst von":"Sebastian Schmidt","Gesch\u00e4tzte Lesezeit":"11\u00a0Minuten","Written by":"Sebastian Schmidt"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#article","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/"},"author":{"name":"Sebastian Schmidt","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/a2ffffeaeaa18b9961297ca47e5f3799"},"headline":"Das Builder Pattern [Teil 2]","datePublished":"2016-09-15T10:45:01+00:00","dateModified":"2022-12-01T10:59:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/"},"wordCount":1476,"commentCount":0,"publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/builder-pattern.png","keywords":["Backend"],"articleSection":["General","Infrastructure"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/","url":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/","name":"Das Builder Pattern [Teil 2] - inovex GmbH","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#primaryimage"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/builder-pattern.png","datePublished":"2016-09-15T10:45:01+00:00","dateModified":"2022-12-01T10:59:50+00:00","description":"Hier stelle ich einige Varianten f\u00fcr die Implementierung eines Builders im Builder Pattern und seiner einzelnen Funktionsaspekte vor.","breadcrumb":{"@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#primaryimage","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/builder-pattern.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2016\/08\/builder-pattern.png","width":2300,"height":876,"caption":"Builder-pattern erkl\u00e4rt anhand von Pizza, Artisckocken und Oliven"},{"@type":"BreadcrumbList","@id":"https:\/\/www.inovex.de\/de\/blog\/das-builder-pattern-teil-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.inovex.de\/de\/"},{"@type":"ListItem","position":2,"name":"Das Builder Pattern [Teil 2]"}]},{"@type":"WebSite","@id":"https:\/\/www.inovex.de\/de\/#website","url":"https:\/\/www.inovex.de\/de\/","name":"inovex GmbH","description":"","publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.inovex.de\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/www.inovex.de\/de\/#organization","name":"inovex GmbH","url":"https:\/\/www.inovex.de\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","width":1921,"height":1081,"caption":"inovex GmbH"},"image":{"@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/inovexde","https:\/\/x.com\/inovexgmbh","https:\/\/www.instagram.com\/inovexlife\/","https:\/\/www.linkedin.com\/company\/inovex","https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ"]},{"@type":"Person","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/a2ffffeaeaa18b9961297ca47e5f3799","name":"Sebastian Schmidt","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/wp-content\/uploads\/Avatar_3000-scaled-96x96.jpg5f905a8b3627c2eb15cdb285c29fe6cf","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/Avatar_3000-scaled-96x96.jpg","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/Avatar_3000-scaled-96x96.jpg","caption":"Sebastian Schmidt"},"url":"https:\/\/www.inovex.de\/de\/blog\/author\/sschmidt\/"}]}},"_links":{"self":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21036","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/comments?post=21036"}],"version-history":[{"count":2,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21036\/revisions"}],"predecessor-version":[{"id":36655,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/21036\/revisions\/36655"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media\/12718"}],"wp:attachment":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media?parent=21036"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/tags?post=21036"},{"taxonomy":"service","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/service?post=21036"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/coauthors?post=21036"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}