Files
java-design-patterns/localization/de/fluent-interface
Stefan SiebersandGitHub cd4753a660 docs: Improve existing German READMEs and add new ones (#3444)
* docs: reformulate text, add links to further languages and paragraph about the book in central README.md
(#2275)

* docs: shorten text for link to payhip
(#2275)

* docs: reformulate german translation for Abstract Document
(#2275)

* Create folder for Abstract Factory

* Create README.md for Abstract Document

* Translate README.md for Abstract Document to German

* correct typo

* docs: add class diagrams for all patterns
(#2275)

* docs: add missing words in abstract-factory.README.md
(#2275)

* docs: Create German README.md for Active Object

#2275
first text part

* docs: finish German translation of README.md for Active Object

* docs: translate actor-model into German

#2295

* docs: add German translation for Acyclic Visitor

#2295

* correct typo

* docs: Translate Singleton into German

#2295

* docs: Translate Prototype into German

#2295

* Delete localization/de/Abstract Factory

* insert line break

* correct typos in actor-model

* realignment of java code block

* docs: translate Adapter Pattern into German

#2295

* Update README.md

change 'lizenz' to 'Lizenz' in badge

* Update README.md

translate 'benefits' and 'trade-offs'

* remove additional bullet point after line break

* correct indentation

* docs: translate Dependency Injection into German

#2295

* docs: translate Bridge into German

#2295

* correct typos

* docs: Translate Builder into German

* delete english text

* little changes in formulation

* Update README.md

change link to image

* docs: remove spanish files
(#2275)

* docs: remove non-translated patterns
(#2275)

* Create README.md

docs: Translate Step Builder into German
#2275

* Create README.md

docs: Translate Fluent Interface into German
#2275

* eager is eifrig, not gierig

* Translate Chain of Responsibility into German

#2275
2026-06-03 20:20:05 +03:00
..

shortTitle, category, language, tag
shortTitle category language tag
Fluent Interface Behavioral de
API design
Code simplification
Decoupling
Object composition
Reactive

Alternativbezeichnungen

  • Fluent API
  • Method Chaining

Zweck

Primäres Ziel des Fluent-Interface-Pattern ist es, eine gut lesbare sprechende API zur Verfügung zu stellen, indem Methodenaufrufe einfach verkettet werden können (Method Chaining). Dieser Ansatz ist ideal, um komplexe Objekte schrittweise zu bauen und generell ein angenehmeres Programmiererlebnis zu erreichen.

Detaillierte Erklärung

Vergleichsbeispiel

Die Bestellung eines frei konfigurierbaren Kaffees in einer Kaffeebar funktioniert ähnlich wie das Fluent-Interface-Pattern. Dabei teilen Sie dem Barista nicht all ihre Wünsche auf einmal mit, sondern nennen schrittweise eine Auswahl nach der anderen, in einem natürlichen Fluss. Sie sagen beispielsweise "Ich möchte einen großen großen Kaffee, mit zwei Espresso-Shots, ohne Zucker, plus Mandelmilch". Diese Aneinanderhängung von Wünschen entspricht dem Verketten von Methodenaufrufen beim Fluent-Interface-Pattern, wodurch der Code zu Objektkonfiguration intuitiv lesbar wird. So wie eine Kaffeekomponente nach der anderen ausgewählt wird, wird im Code eine Methode nach der anderen ausgeführt.

In einfachen Worten:

Fluent Interface bietet eine sprechende, leicht lesbare Schnittstelle zum Code.

Wikipedia sagt:

In der Softwareentwicklung ist Fluent Interface eine objektorientierte API, deren Design auf ausgiebiger Verkettung von Methoden beruht. Ziel ist verbesserte Lesbarkeit des Codes durch eine domänenspezifische Sprache (DSL, domain specific language).

Ablaufdiagramm

Fluent Interface sequence diagram

Programmbeispiel

Wir wollen Zahlen aus einer Liste nach verschiedenen Kriterien auswählen. Dabei können wir die Lesbarkeit des Codes gut mit dem Fluent-Interface-Pattern verbessern.

Der Beispielcode enthält zwei Implementationen eines FluentIterable-Interfaces.

public interface FluentIterable<E> extends Iterable<E> {

  FluentIterable<E> filter(Predicate<? super E> predicate);

  Optional<E> first();

  FluentIterable<E> first(int count);

  Optional<E> last();

  FluentIterable<E> last(int count);

  <T> FluentIterable<T> map(Function<? super E, T> function);

  List<E> asList();

  static <E> List<E> copyToList(Iterable<E> iterable) {
    var copy = new ArrayList<E>();
    iterable.forEach(copy::add);
    return copy;
  }
}

SimpleFluentIterable betreibt eifrige Auswertung und wäre für eine reale Anwendung zu rechenintensiv.

public class SimpleFluentIterable<E> implements FluentIterable<E> {
  // ...
}

LazyFluentIterable wertet erst bei Terminierung der Kette aus.

public class LazyFluentIterable<E> implements FluentIterable<E> {
  // ...
}

Ihre Verwendung zeigen wir mit einer simplen Zahlenliste, die gefiltert, transformiert und zu einer neuen Liste zusammengestellt wird. Das Ergebnis wird anschließend ausgegeben.

public static void main(String[] args) {

    var integerList = List.of(1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68);

    prettyPrint("The initial list contains: ", integerList);

    var firstThreeNegatives = SimpleFluentIterable
            .fromCopyOf(integerList)
            .filter(negatives())
            .first(3)
            .asList();
    prettyPrint("The first three negative values are: ", firstThreeNegatives);


    var lastTwoPositives = SimpleFluentIterable
            .fromCopyOf(integerList)
            .filter(positives())
            .last(2)
            .asList();
    prettyPrint("The last two positive values are: ", lastTwoPositives);

    SimpleFluentIterable
            .fromCopyOf(integerList)
            .filter(number -> number % 2 == 0)
            .first()
            .ifPresent(evenNumber -> LOGGER.info("The first even number is: {}", evenNumber));


    var transformedList = SimpleFluentIterable
            .fromCopyOf(integerList)
            .filter(negatives())
            .map(transformToString())
            .asList();
    prettyPrint("A string-mapped list of negative numbers contains: ", transformedList);


    var lastTwoOfFirstFourStringMapped = LazyFluentIterable
            .from(integerList)
            .filter(positives())
            .first(4)
            .last(2)
            .map(number -> "String[" + number + "]")
            .asList();
    prettyPrint("The lazy list contains the last two of the first four positive numbers "
            + "mapped to Strings: ", lastTwoOfFirstFourStringMapped);

    LazyFluentIterable
            .from(integerList)
            .filter(negatives())
            .first(2)
            .last()
            .ifPresent(number -> LOGGER.info("Last amongst first two negatives: {}", number));
}

Programmausgabe:

08:50:08.260 [main] INFO com.iluwatar.fluentinterface.app.App -- The initial list contains: 1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68.
08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- The first three negative values are: -61, -22, -87.
08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- The last two positive values are: 23, 2.
08:50:08.266 [main] INFO com.iluwatar.fluentinterface.app.App -- The first even number is: 14
08:50:08.267 [main] INFO com.iluwatar.fluentinterface.app.App -- A string-mapped list of negative numbers contains: String[-61], String[-22], String[-87], String[-82], String[-98], String[-68].
08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- The lazy list contains the last two of the first four positive numbers mapped to Strings: String[18], String[6].
08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- Last amongst first two negatives: -22

Verwendung

  • Zum Entwurf vielgenutzter APIs, bei denen die Lesbarkeit des sie verwendenden Codes besonders wichtig ist.
  • Zur schrittweisen Konstruktion komplexer Objekte mit intuitivem und weniger fehleranfälligem Code.
  • Zur Verbesserung der Übersichtlichkeit des Codes und Reduktion von Boilerplate-Code, speziell bei Konfigurationen und Objektkonstruktion.

Tutorials

Reale Anwendungen in Java

Vor- und Nachteile

Vorteile:

  • Signifikant erhöhte Lesbarkeit und Wartbarkeit des Codes
  • Unterstützt die Konstruktion unveränderlicher Objekte, weil die Methoden typischerweise neue Instanzen zurückgeben.
  • Weniger Variablen nötig, da der Kontext durch die Aufrufkette klar wird.

Nachteile:

  • Für Neulinge ist der Code weniger intuitiv.
  • Verkettung von Methoden erschwert das Debuggen.
  • Übermäßige Verwendung kann zu komplexem schwer wartbarem Code führen.

Verwandte Patterns

  • Builder: Verwendet oft Fluent Interface zur schrittweisen Konstruktion. Bei Builder geht es um die Konstruktion komplexer Objekte, bei Fluent Interface um die Methodenverkettung.
  • Chain of Responsibility: Fluent Interfaces können als spezielle Verwendung von Chain of Responsibility betrachtet werden, wo jede Methode in der Kette eine Teilaufgabe behandelt und ihr Ergebnis an die nächste Methode weiterreicht.

Quellen