Skip to content

Commit 506d64c

Browse files
committed
docs: update fluent interface
1 parent 8985c33 commit 506d64c

File tree

1 file changed

+74
-77
lines changed

1 file changed

+74
-77
lines changed

fluentinterface/README.md

Lines changed: 74 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,13 @@ tag:
1717

1818
## Intent
1919

20-
A fluent interface provides an easy-readable, flowing interface, that often mimics a domain specific language. Using this pattern results in code that can be read nearly as human language.
20+
To provide an easily readable, flowing API by chaining method calls.
2121

2222
## Explanation
2323

24-
The Fluent Interface pattern is useful when you want to provide an easy readable, flowing API. Those
25-
interfaces tend to mimic domain specific languages, so they can nearly be read as human languages.
26-
27-
A fluent interface can be implemented using any of
28-
29-
* Method chaining - calling a method returns some object on which further methods can be called.
30-
* Static factory methods and imports.
31-
* Named parameters - can be simulated in Java using static factory methods.
24+
Real-world example
3225

33-
Real world example
34-
35-
> We need to select numbers based on different criteria from the list. It's a great chance to utilize fluent interface pattern to provide readable easy-to-use developer experience.
26+
> Imagine you are at a coffee shop and you want to customize your coffee order. Instead of telling the barista everything at once, you specify each customization step-by-step in a way that flows naturally. For instance, you might say, "I'd like a large coffee, add two shots of espresso, no sugar, and top it with almond milk." This approach is similar to the Fluent Interface design pattern, where you chain together method calls to configure an object in a readable and intuitive manner. Just as you specify each part of your coffee order sequentially, a Fluent Interface allows you to chain method calls to build and configure objects step-by-step in code.
3627
3728
In plain words
3829

@@ -44,6 +35,8 @@ Wikipedia says
4435
4536
**Programmatic Example**
4637

38+
We need to select numbers based on different criteria from the list. It's a great chance to utilize fluent interface pattern to provide readable easy-to-use developer experience.
39+
4740
In this example two implementations of a `FluentIterable` interface are given.
4841

4942
```java
@@ -87,72 +80,74 @@ public class LazyFluentIterable<E> implements FluentIterable<E> {
8780
}
8881
```
8982

90-
Their usage is demonstrated with a simple number list that is filtered, transformed and collected. The
91-
result is printed afterward.
83+
Their usage is demonstrated with a simple number list that is filtered, transformed and collected. The result is printed afterward.
9284

9385
```java
94-
var integerList = List.of(1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68);
95-
96-
prettyPrint("The initial list contains: ", integerList);
97-
98-
var firstFiveNegatives = SimpleFluentIterable
99-
.fromCopyOf(integerList)
100-
.filter(negatives())
101-
.first(3)
102-
.asList();
103-
prettyPrint("The first three negative values are: ", firstFiveNegatives);
104-
105-
106-
var lastTwoPositives = SimpleFluentIterable
107-
.fromCopyOf(integerList)
108-
.filter(positives())
109-
.last(2)
110-
.asList();
111-
prettyPrint("The last two positive values are: ", lastTwoPositives);
112-
113-
SimpleFluentIterable
114-
.fromCopyOf(integerList)
115-
.filter(number -> number % 2 == 0)
116-
.first()
117-
.ifPresent(evenNumber -> LOGGER.info("The first even number is: {}", evenNumber));
118-
119-
120-
var transformedList = SimpleFluentIterable
121-
.fromCopyOf(integerList)
122-
.filter(negatives())
123-
.map(transformToString())
124-
.asList();
125-
prettyPrint("A string-mapped list of negative numbers contains: ", transformedList);
126-
127-
128-
var lastTwoOfFirstFourStringMapped = LazyFluentIterable
129-
.from(integerList)
130-
.filter(positives())
131-
.first(4)
132-
.last(2)
133-
.map(number -> "String[" + valueOf(number) + "]")
134-
.asList();
135-
prettyPrint("The lazy list contains the last two of the first four positive numbers "
136-
+ "mapped to Strings: ", lastTwoOfFirstFourStringMapped);
137-
138-
LazyFluentIterable
139-
.from(integerList)
140-
.filter(negatives())
141-
.first(2)
142-
.last()
143-
.ifPresent(number -> LOGGER.info("Last amongst first two negatives: {}", number));
86+
public static void main(String[] args) {
87+
88+
var integerList = List.of(1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68);
89+
90+
prettyPrint("The initial list contains: ", integerList);
91+
92+
var firstFiveNegatives = SimpleFluentIterable
93+
.fromCopyOf(integerList)
94+
.filter(negatives())
95+
.first(3)
96+
.asList();
97+
prettyPrint("The first three negative values are: ", firstFiveNegatives);
98+
99+
100+
var lastTwoPositives = SimpleFluentIterable
101+
.fromCopyOf(integerList)
102+
.filter(positives())
103+
.last(2)
104+
.asList();
105+
prettyPrint("The last two positive values are: ", lastTwoPositives);
106+
107+
SimpleFluentIterable
108+
.fromCopyOf(integerList)
109+
.filter(number -> number % 2 == 0)
110+
.first()
111+
.ifPresent(evenNumber -> LOGGER.info("The first even number is: {}", evenNumber));
112+
113+
114+
var transformedList = SimpleFluentIterable
115+
.fromCopyOf(integerList)
116+
.filter(negatives())
117+
.map(transformToString())
118+
.asList();
119+
prettyPrint("A string-mapped list of negative numbers contains: ", transformedList);
120+
121+
122+
var lastTwoOfFirstFourStringMapped = LazyFluentIterable
123+
.from(integerList)
124+
.filter(positives())
125+
.first(4)
126+
.last(2)
127+
.map(number -> "String[" + number + "]")
128+
.asList();
129+
prettyPrint("The lazy list contains the last two of the first four positive numbers "
130+
+ "mapped to Strings: ", lastTwoOfFirstFourStringMapped);
131+
132+
LazyFluentIterable
133+
.from(integerList)
134+
.filter(negatives())
135+
.first(2)
136+
.last()
137+
.ifPresent(number -> LOGGER.info("Last amongst first two negatives: {}", number));
138+
}
144139
```
145140

146141
Program output:
147142

148-
```java
149-
The initial list contains: 1, -61, 14, -22, 18, -87, 6, 64, -82, 26, -98, 97, 45, 23, 2, -68.
150-
The first three negative values are: -61, -22, -87.
151-
The last two positive values are: 23, 2.
152-
The first even number is: 14
153-
A string-mapped list of negative numbers contains: String[-61], String[-22], String[-87], String[-82], String[-98], String[-68].
154-
The lazy list contains the last two of the first four positive numbers mapped to Strings: String[18], String[6].
155-
Last amongst first two negatives: -22
143+
```
144+
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.
145+
08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- The first three negative values are: -61, -22, -87.
146+
08:50:08.265 [main] INFO com.iluwatar.fluentinterface.app.App -- The last two positive values are: 23, 2.
147+
08:50:08.266 [main] INFO com.iluwatar.fluentinterface.app.App -- The first even number is: 14
148+
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].
149+
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].
150+
08:50:08.270 [main] INFO com.iluwatar.fluentinterface.app.App -- Last amongst first two negatives: -22
156151
```
157152

158153
## Class diagram
@@ -167,6 +162,10 @@ Use the Fluent Interface pattern when
167162
* Building complex objects step-by-step, and there is a need to make the code more intuitive and less error-prone.
168163
* Enhancing code clarity and reducing the boilerplate code, especially in configurations and object-building scenarios.
169164

165+
## Tutorials
166+
167+
* [An Approach to Internal Domain-Specific Languages in Java (InfoQ)](http://www.infoq.com/articles/internal-dsls-java)
168+
170169
## Known uses
171170

172171
* [Java 8 Stream API](http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html)
@@ -197,10 +196,8 @@ Trade-offs:
197196

198197
## Credits
199198

200-
* [Fluent Interface - Martin Fowler](http://www.martinfowler.com/bliki/FluentInterface.html)
201-
* [Evolutionary architecture and emergent design: Fluent interfaces - Neal Ford](http://www.ibm.com/developerworks/library/j-eaed14/)
202-
* [Internal DSL](http://www.infoq.com/articles/internal-dsls-java)
203-
* [Domain Specific Languages](https://www.amazon.com/gp/product/0321712943/ref=as_li_tl?ie=UTF8&tag=javadesignpat-20&camp=1789&creative=9325&linkCode=as2&creativeASIN=0321712943&linkId=ad8351d6f5be7d8b7ecdb650731f85df)
199+
* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3UrXkh2)
200+
* [Domain Specific Languages](https://amzn.to/3R1UYDA)
204201
* [Effective Java](https://amzn.to/4d4azvL)
205202
* [Java Design Pattern Essentials](https://amzn.to/44bs6hG)
206-
* [Domain-Driven Design: Tackling Complexity in the Heart of Software](https://amzn.to/3UrXkh2)
203+
* [Fluent Interface (Martin Fowler)](http://www.martinfowler.com/bliki/FluentInterface.html)

0 commit comments

Comments
 (0)