diff --git a/src/main/java/com/amigoscode/_6_functionalinterfaces/_3_extending/CombinatorPattern.java b/src/main/java/com/amigoscode/_6_functionalinterfaces/_3_extending/CombinatorPattern.java
index b9a607e..de4f34a 100644
--- a/src/main/java/com/amigoscode/_6_functionalinterfaces/_3_extending/CombinatorPattern.java
+++ b/src/main/java/com/amigoscode/_6_functionalinterfaces/_3_extending/CombinatorPattern.java
@@ -2,30 +2,56 @@
import java.util.function.Function;
+import static com.amigoscode._6_functionalinterfaces._3_extending.CombinatorPattern.ValidationResult.*;
+
+
/**
* Exercise: Combinator Pattern
- *
+ *
* The Combinator Pattern uses functional interfaces to build complex validation
* logic by combining small, reusable validation functions. Each validator is a
* function that takes an object and returns a validation result. Validators can
* be chained using an and() method to create comprehensive validation pipelines.
- *
+ *
* This pattern is powerful because:
- * - Each validator is a simple, testable unit
- * - Validators are composable (combine them freely)
- * - New validators can be added without modifying existing code
+ * - Each validator is a simple, testable unit
+ * - Validators are composable (combine them freely)
+ * - New validators can be added without modifying existing code
*/
public class CombinatorPattern {
- // TODO: 1 - Create a ValidationResult enum with values:
- // SUCCESS, EMAIL_NOT_VALID, NOT_ADULT, NAME_EMPTY
-
-
- // TODO: 2 - Create a Customer record (or class) with three fields:
- // String name, String email, int age
- // Hint for record: record Customer(String name, String email, int age) {}
+ enum ValidationResult {
+ SUCCESS,
+ EMAIL_NOT_VALID,
+ NOT_ADULT,
+ NAME_EMPTY
+ }
+ record Customer(String name, String email, int age) {
+ }
+ @FunctionalInterface
+ interface CustomerValidator extends Function {
+ static CustomerValidator isEmailValid() {
+ return (customer) -> customer.email.contains("@") ? SUCCESS : EMAIL_NOT_VALID;
+ }
+
+ static CustomerValidator isAdult() {
+ return (customer) -> customer.age >= 18 ? SUCCESS : NOT_ADULT;
+ }
+
+ static CustomerValidator isNameNotEmpty() {
+ return customer -> customer.name == null || customer.name.isBlank()
+ ? NAME_EMPTY : ValidationResult.SUCCESS;
+ }
+
+ default CustomerValidator and(CustomerValidator other) {
+ return customer -> {
+ ValidationResult result = this.apply(customer);
+ return result == SUCCESS ? other.apply(customer) : result;
+ };
+ }
+ }
// TODO: 3 - Create a @FunctionalInterface called CustomerValidator that
// extends Function.
// Add three static methods that return CustomerValidator:
@@ -67,10 +93,22 @@ public static void main(String[] args) {
// .and(CustomerValidator.isNameNotEmpty());
+ CustomerValidator fullValidator = CustomerValidator.isEmailValid().and(CustomerValidator.isAdult()).and(CustomerValidator.isNameNotEmpty());
+
// TODO: 6 - Create a valid customer ("Alice", "alice@example.com", 25)
// and validate using fullValidator. Print the result.
// Expected: SUCCESS
+ Customer alice = new Customer("Alice", "alice@example.com", 25);
+ Customer bob = new Customer("Bob", "bob-no-email", 30);
+ Customer young = new Customer("", "young@email.com", 16);
+ Customer unknown = new Customer("", "valid@email.com", 25);
+
+
+ System.out.println(fullValidator.apply(alice));
+ System.out.println(fullValidator.apply(bob));
+ System.out.println(fullValidator.apply(young));
+ System.out.println(fullValidator.apply(unknown));
// TODO: 7 - Create and validate these invalid customers, printing each result:
// a) ("Bob", "bob-no-email", 30) -> Expected: EMAIL_NOT_VALID
diff --git a/src/main/java/com/amigoscode/_6_functionalinterfaces/_3_extending/ExtendingInterfaces.java b/src/main/java/com/amigoscode/_6_functionalinterfaces/_3_extending/ExtendingInterfaces.java
index f7c16e0..08c233d 100644
--- a/src/main/java/com/amigoscode/_6_functionalinterfaces/_3_extending/ExtendingInterfaces.java
+++ b/src/main/java/com/amigoscode/_6_functionalinterfaces/_3_extending/ExtendingInterfaces.java
@@ -7,16 +7,22 @@
/**
* Exercise: Extending Functional Interfaces
- *
+ *
* You can create your own functional interfaces that extend existing ones.
* A Transformer extends Function so that input and output share the
* same type -- useful for chaining transformations on the same data type.
- *
+ *
* You will also add default methods to your functional interface, which is
* allowed as long as there is still exactly one abstract method.
*/
public class ExtendingInterfaces {
+ interface Transformer extends Function {
+
+ default Transformer andThenTransform(Transformer after) {
+ return t -> after.apply(this.apply(t));
+ }
+ }
// TODO: 1 - Create a @FunctionalInterface called Transformer that
// extends Function. It inherits the abstract method apply(T t)
// from Function, so you do NOT need to declare it again.
@@ -34,6 +40,13 @@ public class ExtendingInterfaces {
public static void main(String[] args) {
+ Transformer trimmer = String::trim;
+ Transformer lowerCaser = String::toLowerCase;
+
+ Transformer cleanUp = trimmer.andThenTransform(lowerCaser);
+
+ System.out.println(cleanUp.apply("HELLO WORLD"));
+
// TODO: 3 - Create a Transformer called 'trimmer' that trims
// whitespace from a string using String::trim or s -> s.trim().
@@ -52,6 +65,10 @@ public static void main(String[] args) {
" Alice ", "BOB", " Charlie ", " DIANA "
);
+ List cleanUpList = messyStrings.stream().map(cleanUp).toList();
+
+ cleanUpList.forEach(System.out::println);
+
// TODO: 6 - Apply the 'cleanUp' transformer to each element of
// messyStrings and collect the results into a new List.
// Print the cleaned-up list.