diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/CreditCardStrategy.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/CreditCardStrategy.java new file mode 100644 index 0000000..7287fe2 --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/CreditCardStrategy.java @@ -0,0 +1,11 @@ +package pl.mperor.lab.java.design.pattern.behavioral.strategy.classic; + +import java.time.LocalDate; + +record CreditCardStrategy(String name, String cardNumber, String cvv, LocalDate dateOfExpiry) implements PaymentStrategy { + + @Override + public void pay(double amount) { + System.out.println(amount + " paid by 💳 credit card!"); + } +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/Item.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/Item.java new file mode 100644 index 0000000..3b9eac2 --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/Item.java @@ -0,0 +1,21 @@ +package pl.mperor.lab.java.design.pattern.behavioral.strategy.classic; + +record Item(String upcCode, String name, int priceInCents) { + + public double price() { + return (double) priceInCents / 100; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Item item)) return false; + + return upcCode.equals(item.upcCode); + } + + @Override + public int hashCode() { + return upcCode.hashCode(); + } +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaymentStrategy.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaymentStrategy.java new file mode 100644 index 0000000..45fcbad --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaymentStrategy.java @@ -0,0 +1,6 @@ +package pl.mperor.lab.java.design.pattern.behavioral.strategy.classic; + +public interface PaymentStrategy { + + void pay(double amount); +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaypalStrategy.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaypalStrategy.java new file mode 100644 index 0000000..26066be --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaypalStrategy.java @@ -0,0 +1,9 @@ +package pl.mperor.lab.java.design.pattern.behavioral.strategy.classic; + +public record PaypalStrategy(String emailId, String password) implements PaymentStrategy { + + @Override + public void pay(double amount) { + System.out.println(amount + " paid with 📱 paypal!"); + } +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/Shopping.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/Shopping.java new file mode 100644 index 0000000..4073e9a --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/Shopping.java @@ -0,0 +1,23 @@ +package pl.mperor.lab.java.design.pattern.behavioral.strategy.classic; + +class Shopping { + + private PaymentStrategy strategy; + + Shopping(PaymentStrategy strategy) { + this.strategy = strategy; + } + + void setStrategy(PaymentStrategy strategy) { + this.strategy = strategy; + } + + void pay(ShoppingCart cart) { + pay(cart, strategy); + } + + void pay(ShoppingCart cart, PaymentStrategy strategy) { + double total = cart.computeTotal(); + strategy.pay(total); + } +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/ShoppingCart.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/ShoppingCart.java new file mode 100644 index 0000000..c2737d7 --- /dev/null +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/ShoppingCart.java @@ -0,0 +1,25 @@ +package pl.mperor.lab.java.design.pattern.behavioral.strategy.classic; + +import java.util.LinkedHashMap; +import java.util.Map; + +class ShoppingCart { + + private final Map itemQuantities = new LinkedHashMap<>(); + + void addItem(Item item) { + addItem(item, 1); + } + + void addItem(Item item, int quantities) { + assert quantities >= 1; + itemQuantities.merge(item, quantities, Integer::sum); + } + + double computeTotal() { + return itemQuantities.entrySet() + .stream() + .mapToDouble(entry -> entry.getKey().price() * entry.getValue()) + .sum(); + } +} diff --git a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/MathUtils.java b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/lightweight/MathUtils.java similarity index 50% rename from DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/MathUtils.java rename to DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/lightweight/MathUtils.java index 0104f99..a9cdb15 100644 --- a/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/MathUtils.java +++ b/DesignPatterns/src/main/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/lightweight/MathUtils.java @@ -1,26 +1,26 @@ -package pl.mperor.lab.java.design.pattern.behavioral.strategy; +package pl.mperor.lab.java.design.pattern.behavioral.strategy.lightweight; import java.util.List; import java.util.function.Predicate; -public class MathUtils { +class MathUtils { - public static int totalValue(List values) { + static int totalValue(List values) { return totalValue(values, _ -> true); } - public static int totalValue(List values, Predicate selector) { + static int totalValue(List values, Predicate selector) { return values.stream() .filter(selector) .mapToInt(e -> e) .sum(); } - public static boolean isEven(int number) { + static boolean isEven(int number) { return number % 2 == 0; } - public static boolean isOdd(int number) { + static boolean isOdd(int number) { return !isEven(number); } } diff --git a/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaymentStrategyTest.java b/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaymentStrategyTest.java new file mode 100644 index 0000000..1a749c1 --- /dev/null +++ b/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/classic/PaymentStrategyTest.java @@ -0,0 +1,41 @@ +package pl.mperor.lab.java.design.pattern.behavioral.strategy.classic; + + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import pl.mperor.lab.common.TestUtils; + +import java.time.LocalDate; + +public class PaymentStrategyTest { + + @Test + public void shouldShoppingAllowToPayWithDifferentPaymentStrategy() { + Shopping shopping = new Shopping(new PaypalStrategy("mypaypall@example.com", "1234")); + ShoppingCart shoppingCart = new ShoppingCart(); + shoppingCart.addItem(new Item("b1", "Smart TV", 999_00)); + shoppingCart.addItem(new Item("b2", "Raspberry Pi", 99_99)); + shoppingCart.addItem(new Item("b3", "DVD Player", 44_95)); + + var out = TestUtils.setTempSystemOut(); + shopping.pay(shoppingCart); + shopping.setStrategy(new CreditCardStrategy("John Doe", "1234 1111 2222 1010", "123", LocalDate.parse("2025-12-31"))); + shopping.pay(shoppingCart); + shopping.pay(shoppingCart, _ -> System.out.println("Fake payment 💰, do not use in production!")); + + var outLines = out.lines(); + Assertions.assertTrue(outLines.getFirst().endsWith("paid with 📱 paypal!")); + Assertions.assertTrue(outLines.getSecond().endsWith("paid by 💳 credit card!")); + Assertions.assertEquals("Fake payment 💰, do not use in production!", outLines.getThird()); + TestUtils.resetSystemOut(); + } + + @Test + public void shouldReturnCorrectTotalPriceWhenItemsAdded() { + var cart = new ShoppingCart(); + cart.addItem(new Item("A1", "iPhone X", 2000 * 100)); + cart.addItem(new Item("A2", "Laptop", 2500 * 100), 2); + cart.addItem(new Item("A3", "Tablet Neo", 199 * 100), 3); + Assertions.assertEquals(7597d, cart.computeTotal()); + } +} \ No newline at end of file diff --git a/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/LightweightStrategyTest.java b/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/lightweight/SelectorStrategyTest.java similarity index 70% rename from DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/LightweightStrategyTest.java rename to DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/lightweight/SelectorStrategyTest.java index 8ce3731..2f92ed4 100644 --- a/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/LightweightStrategyTest.java +++ b/DesignPatterns/src/test/java/pl/mperor/lab/java/design/pattern/behavioral/strategy/lightweight/SelectorStrategyTest.java @@ -1,14 +1,14 @@ -package pl.mperor.lab.java.design.pattern.behavioral.strategy; +package pl.mperor.lab.java.design.pattern.behavioral.strategy.lightweight; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.util.List; -public class LightweightStrategyTest { +public class SelectorStrategyTest { @Test - public void testTotalValueStrategy() { + public void testMathUtilsWithSelectorStrategy() { var values = List.of(1, 2, 3, 4); Assertions.assertEquals(10, MathUtils.totalValue(values)); Assertions.assertEquals(6, MathUtils.totalValue(values, MathUtils::isEven));