Skip to content

Commit 684b2e2

Browse files
authored
feat: Function composition (iluwatar#2954)
* feature: Implement Virtual Proxy pattern iluwatar#2940 * feature: Implement Virtual Proxy pattern iluwatar#2940 * feature: Implement Virtual Proxy pattern iluwatar#2940 * feature: Implement Virtual Proxy pattern iluwatar#2940 * feature: Implement Virtual Proxy pattern iluwatar#2940 * feature: Implement Virtual Proxy pattern, tests added * feature: Implement Virtual Proxy pattern, tests added * feature: Implement Virtual Proxy pattern, tests added * feature: Implement Virtual Proxy pattern, tests added * feature: Implement Virtual Proxy pattern, tests added * feature: Implement function composition pattern iluwatar#2897 * task: isolate virtual proxy pattern * task: isolate virtual proxy pattern * refactoring: readme.md
1 parent 68ef414 commit 684b2e2

File tree

10 files changed

+495
-0
lines changed

10 files changed

+495
-0
lines changed

function-composition/.gitignore

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
################## Eclipse ######################
2+
target
3+
.metadata
4+
.settings
5+
.classpath
6+
.project
7+
*.class
8+
tmp/
9+
*.tmp
10+
*.bak
11+
*~.nib
12+
local.properties
13+
.loadpath
14+
.recommenders
15+
.DS_Store
16+
17+
####### Java annotation processor (APT) ########
18+
.factorypath
19+
20+
################ Package Files ##################
21+
*.jar
22+
*.war
23+
*.ear
24+
*.swp
25+
datanucleus.log
26+
/bin/
27+
*.log
28+
event-sourcing/Journal.json
29+
30+
################## Checkstyle ###################
31+
.checkstyle
32+
33+
##################### STS #######################
34+
.apt_generated
35+
.springBeans
36+
.sts4-cache
37+
38+
################# IntelliJ IDEA #################
39+
.idea
40+
*.iws
41+
*.iml
42+
*.ipr
43+
44+
################### NetBeans ####################
45+
/nbproject/private/
46+
/nbbuild/
47+
/dist/
48+
/nbdist/
49+
/.nb-gradle/
50+
build/
51+
!**/src/main/**/build/
52+
!**/src/test/**/build/
53+
54+
#################### VS Code ####################
55+
.vscode/
56+
57+
#################### Java Design Patterns #######
58+
etc/Java Design Patterns.urm.puml
59+
serialized-entity/output.txt

function-composition/README.md

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
title: Function Composition
3+
category: Behavioral
4+
language: en
5+
tag:
6+
- Functional Programming
7+
- Functional decomposition
8+
- Java
9+
---
10+
11+
## Also known as
12+
13+
Functional Composition
14+
15+
## Intent
16+
To enable creating complex functions by composing simpler ones, enhancing modularity and reusability of function-based logic.
17+
18+
## Explanation
19+
20+
Real-world example:
21+
22+
> In financial software, functions that calculate various financial metrics can be composed to provide detailed analysis. For instance, a function that calculates interest can be composed with another that adjusts for taxes, allowing for a modular yet comprehensive financial assessment tool.
23+
24+
In plain words:
25+
26+
> The Function Composer pattern allows building complex functions by combining simpler ones, making it easier to manage, test, and reuse individual pieces of functionality.
27+
28+
Wikipedia says:
29+
30+
> Function composition is an act or mechanism to combine simple functions to build more complicated ones. Like the usual composition of functions in mathematics, the result of each function is passed as the argument of the next, and the result of the last one is the result of the whole.
31+
32+
**Programmatic Example**
33+
34+
Here is how the Function Composer pattern might be implemented and used in Java:
35+
36+
```java
37+
public class FunctionComposer {
38+
39+
public static Function<Integer, Integer> composeFunctions(Function<Integer, Integer> f1, Function<Integer, Integer> f2) {
40+
return f1.andThen(f2);
41+
}
42+
}
43+
```
44+
```java
45+
public class App {
46+
public static void main(String[] args) {
47+
Function<Integer, Integer> timesTwo = x -> x * 2;
48+
Function<Integer, Integer> square = x -> x * x;
49+
50+
Function<Integer, Integer> composedFunction = FunctionComposer.composeFunctions(timesTwo, square);
51+
52+
int result = composedFunction.apply(3);
53+
logger.info("Result of composing 'timesTwo' and 'square' functions applied to 3 is: " + result);
54+
}
55+
}
56+
```
57+
58+
Result:
59+
```
60+
Result of composing 'timesTwo' and 'square' functions applied to 3 is: 36 // Result will be 36 (3 * 2 = 6, 6 * 6 = 36)
61+
```
62+
63+
Use ``.compose()`` function when you need pre-compose and ``.andThen()`` function when you need post-compose.
64+
65+
## Sequence diagram
66+
67+
![Functional Composer Diagram](./etc/function.composition.urm.png "function composition")
68+
69+
## Applicability
70+
71+
Use the Function Composer pattern when:
72+
73+
* You want to create a pipeline of operations where the output of one function is the input to another.
74+
* You need to enhance the clarity and quality of your code by structuring complex function logic into simpler, reusable components.
75+
* You are working in a functional programming environment or a language that supports higher-order functions.
76+
77+
## Tutorials
78+
79+
[Function Composition in Java](https://functionalprogramming.medium.com/function-composition-in-java-beaf39426f52)
80+
81+
## Known uses
82+
83+
* Stream processing in Java 8 and above
84+
* Query builders in ORM libraries
85+
* Middleware composition in web frameworks
86+
87+
## Consequences
88+
89+
Benefits:
90+
91+
* High reusability of composed functions.
92+
* Increased modularity, making complex functions easier to understand and maintain.
93+
* Flexible and dynamic creation of function pipelines at runtime.
94+
*
95+
Drawbacks:
96+
97+
* Potentially higher complexity when debugging composed functions.
98+
* Overhead from creating and managing multiple function objects in memory-intensive scenarios.
99+
100+
## Related patterns
101+
102+
* Chain of Responsibility
103+
* Decorator
104+
* Strategy
105+
106+
## Credits
107+
108+
[Functional Programming in Java](https://www.baeldung.com/java-functional-programming)
109+
[Function Composition in Java](https://functionalprogramming.medium.com/function-composition-in-java-beaf39426f52)
Loading
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
@startuml
2+
skinparam monochrome true
3+
4+
participant "App" as App
5+
participant "FunctionComposer" as Composer
6+
participant "Function<Integer, Integer>" as F1
7+
8+
create F1
9+
App -> F1 : func1 = x -> x * 2
10+
create F1
11+
App -> F1 : func2 = x -> x * x
12+
13+
App -> Composer : func1, func2
14+
activate Composer
15+
Composer -> F1 : func1.andThen(func2)
16+
deactivate Composer
17+
activate F1
18+
F1 -> App : composedFunction
19+
deactivate F1
20+
21+
@enduml

function-composition/pom.xml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
5+
6+
The MIT License
7+
Copyright © 2014-2022 Ilkka Seppälä
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
-->
28+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
29+
<modelVersion>4.0.0</modelVersion>
30+
<parent>
31+
<groupId>com.iluwatar</groupId>
32+
<artifactId>java-design-patterns</artifactId>
33+
<version>1.26.0-SNAPSHOT</version>
34+
</parent>
35+
<artifactId>function-composition</artifactId>
36+
<dependencies>
37+
<dependency>
38+
<groupId>org.junit.jupiter</groupId>
39+
<artifactId>junit-jupiter-engine</artifactId>
40+
<scope>test</scope>
41+
</dependency>
42+
<dependency>
43+
<groupId>junit</groupId>
44+
<artifactId>junit</artifactId>
45+
<scope>test</scope>
46+
</dependency>
47+
</dependencies>
48+
<build>
49+
<plugins>
50+
<plugin>
51+
<groupId>org.apache.maven.plugins</groupId>
52+
<artifactId>maven-assembly-plugin</artifactId>
53+
<executions>
54+
<execution>
55+
<configuration>
56+
<archive>
57+
<manifest>
58+
<mainClass>App</mainClass>
59+
</manifest>
60+
</archive>
61+
</configuration>
62+
</execution>
63+
</executions>
64+
</plugin>
65+
</plugins>
66+
</build>
67+
</project>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
3+
*
4+
* The MIT License
5+
* Copyright © 2014-2022 Ilkka Seppälä
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package com.iluwatar.function.composition;
26+
27+
import java.util.function.Function;
28+
import org.slf4j.LoggerFactory;
29+
30+
/**
31+
* Main application class to demonstrate the use of function composition.
32+
*/
33+
public class App {
34+
35+
/**
36+
* Main method to demonstrate function composition using FunctionComposer.
37+
*
38+
* @param args command line arguments (not used)
39+
*/
40+
public static void main(String[] args) {
41+
final var logger = LoggerFactory.getLogger(App.class);
42+
Function<Integer, Integer> timesTwo = x -> x * 2;
43+
Function<Integer, Integer> square = x -> x * x;
44+
45+
Function<Integer, Integer> composedFunction = FunctionComposer.composeFunctions(timesTwo, square);
46+
47+
int result = composedFunction.apply(3);
48+
logger.info("Result of composing 'timesTwo' and 'square' functions applied to 3 is: " + result);
49+
}
50+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
3+
*
4+
* The MIT License
5+
* Copyright © 2014-2022 Ilkka Seppälä
6+
*
7+
* Permission is hereby granted, free of charge, to any person obtaining a copy
8+
* of this software and associated documentation files (the "Software"), to deal
9+
* in the Software without restriction, including without limitation the rights
10+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
* copies of the Software, and to permit persons to whom the Software is
12+
* furnished to do so, subject to the following conditions:
13+
*
14+
* The above copyright notice and this permission notice shall be included in
15+
* all copies or substantial portions of the Software.
16+
*
17+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23+
* THE SOFTWARE.
24+
*/
25+
package com.iluwatar.function.composition;
26+
27+
import java.util.function.Function;
28+
29+
/**
30+
* Class for composing functions using the Function Composition pattern.
31+
* Provides a static method to compose two functions using the 'andThen' method.
32+
*/
33+
public class FunctionComposer {
34+
35+
/**
36+
* Composes two functions where the output of the first function becomes
37+
* the input of the second function.
38+
*
39+
* @param f1 the first function to apply
40+
* @param f2 the second function to apply after the first
41+
* @return a composed function that applies f1 and then f2
42+
*/
43+
public static Function<Integer, Integer> composeFunctions(Function<Integer, Integer> f1, Function<Integer, Integer> f2) {
44+
return f1.andThen(f2);
45+
}
46+
}

0 commit comments

Comments
 (0)