mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-10-13 10:15:44 +00:00
docs: update function composition pattern
This commit is contained in:
1 parent
ce2e5f75d8
commit
8ca487e96c
4 files changed
+28
-28
No files matched your search
@@ -5,18 +5,20 @@ description: "Learn about the Function Composition design pattern in Java. Disco
|
|||||||
category: Functional
|
category: Functional
|
||||||
language: en
|
language: en
|
||||||
tag:
|
tag:
|
||||||
|
- Code simplification
|
||||||
- Composition
|
- Composition
|
||||||
|
- Functional decomposition
|
||||||
|
- Reusability
|
||||||
---
|
---
|
||||||
|
|
||||||
## Also known as
|
## Also known as
|
||||||
|
|
||||||
* Function Chaining
|
* Function Chaining
|
||||||
* Function Pipelining
|
* Higher-Order Function Wrapping
|
||||||
* Functional Composition
|
|
||||||
|
|
||||||
## Intent of Function Composition Design Pattern
|
## Intent of Function Composition Design Pattern
|
||||||
|
|
||||||
The Function Composition design pattern in Java enables the creation of complex functions by combining simpler ones. This enhances modular code and reusability, crucial for maintainable software development.
|
Combine multiple small functions into a single operation that executes them in a sequence, producing a new function as the result.
|
||||||
|
|
||||||
## Detailed Explanation of Function Composition Pattern with Real-World Examples
|
## Detailed Explanation of Function Composition Pattern with Real-World Examples
|
||||||
|
|
||||||
@@ -40,24 +42,24 @@ Sequence diagram
|
|||||||
|
|
||||||
## Programmatic Example of Function Composition Pattern in Java
|
## Programmatic Example of Function Composition Pattern in Java
|
||||||
|
|
||||||
In the functional programming paradigm, function composition is a powerful technique. For instance, in Java, you can use higher-order functions to compose operations like multiplying and squaring numbers.
|
In the functional programming paradigm, function composition is a powerful technique. For instance, in Java, you can use higher-order functions to combine operations like multiplying and squaring numbers.
|
||||||
|
|
||||||
Using Java's functional interfaces, we can define simple functions and compose them. Here's how function composition works in Java.
|
Using Java's functional interfaces, we can define simple functions and compose them. Here's how function composition works in Java.
|
||||||
|
|
||||||
Let's start with defining two simple functions. In this case, we have a function `timesTwo` that multiplies its input by 2, and a function `square` that squares its input.
|
Let's start with defining two simple functions. In this case, we have a function `timesTwo` that multiplies its input by 2, and a function `square` that squares its input:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Function<Integer, Integer> timesTwo = x -> x * 2;
|
Function<Integer, Integer> timesTwo = x -> x * 2;
|
||||||
Function<Integer, Integer> square = x -> x * x;
|
Function<Integer, Integer> square = x -> x * x;
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, we use the `FunctionComposer` class to compose these two functions into a new function. The `composeFunctions` method takes two functions as arguments and returns a new function that is the composition of the input functions.
|
Next, we use the `FunctionComposer` class to compose these two functions into a new function. The `composeFunctions` method takes two functions as arguments and returns a new function that is the composition of the input functions:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
Function<Integer, Integer> composedFunction = FunctionComposer.composeFunctions(timesTwo, square);
|
Function<Integer, Integer> composedFunction = FunctionComposer.composeFunctions(timesTwo, square);
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, we apply the composed function to an input value. In this case, we apply it to the number 3. The result is the square of the number 3 multiplied by 2, which is 36.
|
Finally, we apply the composed function to an input value. In this case, we apply it to the number 3. The result is the square of the number 3 multiplied by 2, which is 36:
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
@@ -84,10 +86,9 @@ This example demonstrates how the Function Composition pattern can be used to cr
|
|||||||
|
|
||||||
Use the Function Composition pattern when:
|
Use the Function Composition pattern when:
|
||||||
|
|
||||||
* You want to create a pipeline of operations in Java. This enhances code clarity and quality by structuring complex logic into simpler, reusable components.
|
* When you want to build complex transformations by chaining smaller, reusable functions in Java.
|
||||||
* You are working in a functional programming environment or a language that supports higher-order functions.
|
* When the logic is best expressed through a series of operations that naturally feed one into another.
|
||||||
* When you want to avoid deep nesting of function calls and instead build a pipeline of operations.
|
* When you want to reduce code duplication and improve readability by isolating each operation in its own function.
|
||||||
* When aiming to promote immutability and side-effect-free functions in your design.
|
|
||||||
|
|
||||||
## Function Composition Pattern Java Tutorials
|
## Function Composition Pattern Java Tutorials
|
||||||
|
|
||||||
@@ -96,31 +97,28 @@ Use the Function Composition pattern when:
|
|||||||
|
|
||||||
## Real-World Applications of Function Composition Pattern in Java
|
## Real-World Applications of Function Composition Pattern in Java
|
||||||
|
|
||||||
* Stream processing in Java 8 and above
|
* Java’s Stream API, where map and filter are composed for data transformations.
|
||||||
* Query builders in ORM libraries
|
* Google Guava’s Function utilities.
|
||||||
* Middleware composition in web frameworks
|
* Apache Commons libraries that provide utilities for chaining functions.
|
||||||
|
|
||||||
## Benefits and Trade-offs of Function Composition Pattern
|
## Benefits and Trade-offs of Function Composition Pattern
|
||||||
|
|
||||||
Benefits:
|
Benefits:
|
||||||
|
|
||||||
* High reusability of composed functions.
|
* Encourages highly modular and reusable code.
|
||||||
* Increased modularity, making complex functions easier to understand and maintain.
|
* Simplifies complex logic by breaking it down into smaller, testable units.
|
||||||
* Flexible and dynamic creation of function pipelines at runtime.
|
* Makes the code more expressive and easier to maintain.
|
||||||
* Enhances readability by structuring code in a linear, declarative manner.
|
|
||||||
* Facilitates easier testing of individual functions.
|
|
||||||
|
|
||||||
Trade-offs:
|
Trade-offs:
|
||||||
|
|
||||||
* Potentially higher complexity when debugging composed functions.
|
* Excessive chaining can reduce readability if taken too far.
|
||||||
* Overhead from creating and managing multiple function objects in memory-intensive scenarios.
|
* May introduce performance overhead due to multiple function calls.
|
||||||
* May require a paradigm shift for developers unfamiliar with functional programming concepts.
|
* Errors can be harder to trace in a deeply composed function pipeline.
|
||||||
|
|
||||||
## Related Java Design Patterns
|
## Related Java Design Patterns
|
||||||
|
|
||||||
* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/) - Both patterns allow processing to be broken down into a series of steps, but Functional Composition focuses on function composition rather than responsibility delegation.
|
* [Chain of Responsibility](https://java-design-patterns.com/patterns/chain-of-responsibility/) - Both patterns allow processing to be broken down into a series of steps, but Functional Composition focuses on function composition rather than responsibility delegation.
|
||||||
* [Decorator](https://java-design-patterns.com/patterns/decorator/) - Similar in combining behaviors, but Decorator applies additional behavior to objects, while Functional Composition builds new functions.
|
* [Composite](https://java-design-patterns.com/patterns/composite/): Also deals with combining smaller components, though it is typically about object structure rather than function operations.
|
||||||
* [Strategy](https://java-design-patterns.com/patterns/strategy/) - Provides interchangeable functions (strategies), which can be composed in Functional Composition.
|
|
||||||
|
|
||||||
## References and Credits
|
## References and Credits
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,10 @@
|
|||||||
package com.iluwatar.function.composition;
|
package com.iluwatar.function.composition;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import org.slf4j.LoggerFactory;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/** Main application class to demonstrate the use of function composition. */
|
/** Main application class to demonstrate the use of function composition. */
|
||||||
|
@Slf4j
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,7 +37,6 @@ public class App {
|
|||||||
* @param args command line arguments (not used)
|
* @param args command line arguments (not used)
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
final var logger = LoggerFactory.getLogger(App.class);
|
|
||||||
Function<Integer, Integer> timesTwo = x -> x * 2;
|
Function<Integer, Integer> timesTwo = x -> x * 2;
|
||||||
Function<Integer, Integer> square = x -> x * x;
|
Function<Integer, Integer> square = x -> x * x;
|
||||||
|
|
||||||
@@ -44,6 +44,6 @@ public class App {
|
|||||||
FunctionComposer.composeFunctions(timesTwo, square);
|
FunctionComposer.composeFunctions(timesTwo, square);
|
||||||
|
|
||||||
int result = composedFunction.apply(3);
|
int result = composedFunction.apply(3);
|
||||||
logger.info("Result of composing 'timesTwo' and 'square' functions applied to 3 is: " + result);
|
LOGGER.info("Result of composing 'timesTwo' and 'square' functions applied to 3 is: " + result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
@@ -32,6 +32,8 @@ import java.util.function.Function;
|
|||||||
*/
|
*/
|
||||||
public class FunctionComposer {
|
public class FunctionComposer {
|
||||||
|
|
||||||
|
private FunctionComposer() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Composes two functions where the output of the first function becomes the input of the second
|
* Composes two functions where the output of the first function becomes the input of the second
|
||||||
* function.
|
* function.
|
||||||
|
|||||||
+1
-1
@@ -30,7 +30,7 @@ import java.util.function.Function;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
/** Test class for FunctionComposer. */
|
/** Test class for FunctionComposer. */
|
||||||
public class FunctionComposerTest {
|
class FunctionComposerTest {
|
||||||
|
|
||||||
/** Tests the composition of two functions. */
|
/** Tests the composition of two functions. */
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in new issue
Block a user