diff --git a/java-design-patterns b/java-design-patterns new file mode 160000 index 000000000000..b375919db5e5 --- /dev/null +++ b/java-design-patterns @@ -0,0 +1 @@ +Subproject commit b375919db5e5309c2bd3e524eb85634d65cb0336 diff --git a/pom.xml b/pom.xml index ef3a39265d53..b982bbed5189 100644 --- a/pom.xml +++ b/pom.xml @@ -218,6 +218,7 @@ function-composition microservices-distributed-tracing microservices-idempotent-consumer + session-facade @@ -268,11 +269,6 @@ slf4j-api ${slf4j.version} - - ch.qos.logback - logback-classic - ${logback.version} - ch.qos.logback logback-core diff --git a/session-facade/README.md b/session-facade/README.md new file mode 100644 index 000000000000..cb5db50f6f3d --- /dev/null +++ b/session-facade/README.md @@ -0,0 +1,146 @@ +--- +title: "Session Facade Pattern in Java: Simplifying Complex System Interfaces" +shortTitle: Session Facade +description: "Learn how to implement the Session Facade Design Pattern in Java to create a unified interface for complex subsystems. Simplify your code and enhance maintainability with practical examples and use cases." +category: Structural +language: en +tag: + - Abstraction + - API design + - Code simplification + - Decoupling + - Encapsulation + - Gang Of Four + - Interface +--- + +## Also known as + +* Session Facade + +## Intent of Session Facade Design Pattern + +Abstracting the underlying business object interactions by providing a service layer that exposes only the required interfaces + +## Detailed Explanation of Session Facade Pattern with Real-World Examples + +Real-world example + +> In an e-commerce website, users interact with several subsystems like product catalogs, shopping carts, +> payment services, and order management. The Session Facade pattern provides a simplified, centralized interface for these subsystems, +> allowing the client to interact with just a few high-level methods (e.g., addToCart(), placeOrder(), selectPaymentMethod()), instead of directly communicating with each subsystem, using a facade supports low coupling between classes and high cohesion within each service, allowing them to focus on their specific responsibilities. + +In plain words + +> The Session Facade design pattern is an excellent choice for decoupling complex components of the system that need to be interacting frequently. + +## Programmatic Example of Session Facade Pattern in Java + +The Session Facade design pattern is a structural design pattern that provides a simplified interface to a set of complex subsystems, reducing the complexity for the client. This pattern is particularly useful in situations where the client needs to interact with multiple services or systems but doesn’t need to know the internal workings of each service. + +In the context of an e-commerce website, imagine a system where users can browse products, add items to the shopping cart, process payments, and place orders. Instead of the client directly interacting with each individual service (cart, order, payment), the Session Facade provides a single, unified interface for these operations. + +Example Scenario: +In this example, the ShoppingFacade class manages interactions with three subsystems: the `CartService`, `OrderService`, and `PaymentService`. The client interacts with the facade to perform high-level operations like adding items to the cart, placing an order, and selecting a payment method. + +Here’s a simplified programmatic example: +```java +public class App { + public static void main(String[] args) { + ShoppingFacade shoppingFacade = new ShoppingFacade(); + shoppingFacade.addToCart(1); + shoppingFacade.order(); + shoppingFacade.selectPaymentMethod("cash"); + } +} +``` + +The `ShoppingFacade` acts as an intermediary that facilitates interaction between different services promoting low coupling between these services. +```java +public class ShoppingFacade { + List productCatalog; + List cart; + CartService cartService; + OrderService orderService; + PaymentService paymentService; + + public ShoppingFacade() { + productCatalog = new ArrayList<>(); + productCatalog.add(new Product(1, "Wireless Mouse", 25.99, "Ergonomic wireless mouse with USB receiver.")); + productCatalog.add(new Product(2, "Gaming Keyboard", 79.99, "RGB mechanical gaming keyboard with programmable keys.")); + cart = new ArrayList<>(); + cartService = new CartService(cart, productCatalog); + orderService = new OrderService(cart); + paymentService = new PaymentService(); + } + + public void addToCart(int productId) { + this.cartService.addToCart(productId); + } + + public void removeFromCart(int productId) { + this.cartService.removeFromCart(productId); + } + + public void order() { + this.orderService.order(); + } + + public void selectPaymentMethod(String method) { + this.paymentService.selectPaymentMethod(method); + } +} +``` + +Console output for starting the `App` class's `main` method: + +``` +19:43:17.883 [main] INFO com.iluwatar.sessionfacade.CartService -- ID: 1 +Name: Wireless Mouse +Price: $25.99 +Description: Ergonomic wireless mouse with USB receiver. successfully added to the cart +19:43:17.910 [main] INFO com.iluwatar.sessionfacade.OrderService -- Client has chosen to order [ID: 1 +Name: Wireless Mouse +Price: $25.99 +Description: Ergonomic wireless mouse with USB receiver.] +19:43:17.910 [main] INFO com.iluwatar.sessionfacade.PaymentService -- Client have chosen cash payment option +``` + +This is a basic example of the Session Facade design pattern. The actual implementation would depend on specific requirements of your application. + +## When to Use the Session Facade Pattern in Java + +* Use when building complex applications with multiple interacting services, where you want to simplify the interaction between various subsystems. +* Ideal for decoupling complex systems that need to interact but should not be tightly coupled. +* Suitable for applications where you need a single point of entry to interact with multiple backend services, like ecommerce platforms, booking systems, or order management systems. + +## Real-World Applications of Server Session Pattern in Java + +* Enterprise JavaBeans (EJB) +* Java EE (Jakarta EE) Applications + +## Benefits and Trade-offs of Server Session Pattern + + +* Simplifies client-side logic by providing a single entry point for complex operations across multiple services. +* Decouples components of the application, making them easier to maintain, test, and modify without affecting other parts of the system. +* Improves modularity by isolating the implementation details of subsystems from the client. +* Centralizes business logic in one place, making the code easier to manage and update. + +## Trade-offs: + +* Potential performance bottleneck: Since all requests pass through the facade, it can become a bottleneck if not optimized. +* Increased complexity: If the facade becomes too large or complex, it could counteract the modularity it aims to achieve. +* Single point of failure: If the facade encounters issues, it could affect the entire system's operation, making it crucial to handle errors and exceptions properly. + +## Related Java Design Patterns + +* [Facade](https://java-design-patterns.com/patterns/facade/): The Session Facade pattern is a specific application of the more general Facade pattern, which simplifies access to complex subsystems. +* [Command](https://java-design-patterns.com/patterns/command/): Useful for encapsulating requests and passing them to the session facade, which could then manage the execution order. +* [Singleton](https://java-design-patterns.com/patterns/singleton/): Often used to create a single instance of the session facade for managing the entire workflow of a subsystem. + +## References and Credits + +* [Core J2EE Patterns: Best Practices and Design Strategies](https://amzn.to/4cAbDap) +* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI) +* [Patterns of Enterprise Application Architecture](https://amzn.to/3WfKBPR) diff --git a/session-facade/etc/session-facade.urm.png b/session-facade/etc/session-facade.urm.png new file mode 100644 index 000000000000..5e62265e874d Binary files /dev/null and b/session-facade/etc/session-facade.urm.png differ diff --git a/session-facade/etc/session-facade.urm.puml b/session-facade/etc/session-facade.urm.puml new file mode 100644 index 000000000000..bdcd730a72d3 --- /dev/null +++ b/session-facade/etc/session-facade.urm.puml @@ -0,0 +1,50 @@ +@startuml +package com.iluwatar.sessionfacade { + class App { + + App() + + main(args : String[]) {static} + } + class CartService { + - LOGGER : Logger {static} + - cart : List + - productCatalog : List + + CartService(cart : List, productCatalog : List) + + addToCart(productId : int) + + removeFromCart(productId : int) + } + class OrderService { + - LOGGER : Logger {static} + - products : List + + OrderService(products : List) + + order() + } + class PaymentService { + - LOGGER : Logger {static} + + PaymentService() + + cashPayment() + + creditCardPayment() + + selectPaymentMethod(method : String) + } + class ProductCatalogService { + - LOGGER : Logger {static} + - products : List + + ProductCatalogService(products : List) + + getProductDetails(productId : int) + } + class ShoppingFacade { + ~ cart : List + ~ cartService : CartService + ~ orderService : OrderService + ~ paymentService : PaymentService + ~ productCatalog : List + + ShoppingFacade() + + addToCart(productId : int) + + order() + + removeFromCart(productId : int) + + selectPaymentMethod(method : String) + } +} +ShoppingFacade --> "-cartService" CartService +ShoppingFacade --> "-paymentService" PaymentService +ShoppingFacade --> "-orderService" OrderService +@enduml \ No newline at end of file diff --git a/session-facade/pom.xml b/session-facade/pom.xml new file mode 100644 index 000000000000..8fa386551064 --- /dev/null +++ b/session-facade/pom.xml @@ -0,0 +1,79 @@ + + + + 4.0.0 + + com.iluwatar + java-design-patterns + 1.26.0-SNAPSHOT + + + session-facade + + + 17 + 17 + UTF-8 + + + + org.testng + testng + RELEASE + test + + + junit + junit + test + + + org.junit.jupiter + junit-jupiter + test + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + + ch.qos.logback + logback-classic + 1.5.6 + + + + \ No newline at end of file diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/App.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/App.java new file mode 100644 index 000000000000..c5adbf4cbad2 --- /dev/null +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/App.java @@ -0,0 +1,49 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package com.iluwatar.sessionfacade; + +/** + * The type App. + */ +public class App { + /** + * The entry point of application. + * + * @param args the input arguments + */ + public static void main(String[] args) { + ShoppingFacade shoppingFacade1 = new ShoppingFacade(); + shoppingFacade1.addToCart(1); + shoppingFacade1.order(); + shoppingFacade1.selectPaymentMethod("cash"); + + ShoppingFacade shoppingFacade2 = new ShoppingFacade(); + shoppingFacade1.addToCart(2); + shoppingFacade2.order(); + shoppingFacade2.selectPaymentMethod("credit"); + + } +} \ No newline at end of file diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/CartService.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/CartService.java new file mode 100644 index 000000000000..0c2b6191d348 --- /dev/null +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/CartService.java @@ -0,0 +1,80 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + +/** + * The type Cart service. + */ +@Slf4j +public class CartService { + + private final List cart; + private final List productCatalog; + + /** + * Instantiates a new Cart service. + * + * @param cart the cart + * @param productCatalog the product catalog + */ + public CartService(List cart, List productCatalog) { + this.cart = cart; + this.productCatalog = productCatalog; + } + + /** + * Add to cart. + * + * @param productId the product id + */ + public void addToCart(int productId) { + for (Product product : productCatalog) { + if (productId == product.id()) { + this.cart.add(product); + LOGGER.info("{} successfully added to the cart", product); + return; + } + } + LOGGER.info("No product is found with id {}", productId); + } + + /** + * Remove from cart. + * + * @param productId the product id + */ + public void removeFromCart(int productId) { + for (Product product : productCatalog) { + if (productId == product.id()) { + this.cart.remove(product); + LOGGER.info("{} successfully removed from the cart", product); + return; + } + } + LOGGER.info("No product is found with the id {}", productId); + } +} diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/OrderService.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/OrderService.java new file mode 100644 index 000000000000..82f322bd932d --- /dev/null +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/OrderService.java @@ -0,0 +1,53 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; +import java.util.List; +import lombok.extern.slf4j.Slf4j; + + +/** + * The type Order service. + */ +@Slf4j +public class OrderService { + private final List cart; + + /** + * Instantiates a new Order service. + * + * @param cart the cart + */ + public OrderService(List cart) { + this.cart = cart; + } + + /** + * Order. + */ + public void order() { + LOGGER.info("Client has chosen to order {}", cart); + cart.clear(); + } +} diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/PaymentService.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/PaymentService.java new file mode 100644 index 000000000000..ff3de3e26c25 --- /dev/null +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/PaymentService.java @@ -0,0 +1,64 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The type Payment service. + */ + +public class PaymentService { + public static Logger LOGGER = LoggerFactory.getLogger(PaymentService.class); + + /** + * Select payment method. + * + * @param method the method + */ + public void selectPaymentMethod(String method) { + if (method.equals("cash")) { + cashPayment(); + } else if (method.equals("credit")) { + creditCardPayment(); + } else { + LOGGER.info("Unspecified payment method type"); + } + } + + /** + * Cash payment. + */ + public void cashPayment() { + LOGGER.info("Client have chosen cash payment option"); + } + + /** + * Credit card payment. + */ + public void creditCardPayment() { + LOGGER.info("Client have chosen credit card payment option"); + } +} diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/Product.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/Product.java new file mode 100644 index 000000000000..fb234818da2b --- /dev/null +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/Product.java @@ -0,0 +1,41 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; + +import lombok.Getter; + +/** + * The type Product. + */ +public record Product(int id, String name, double price, String description) { + + @Override + public String toString() { + return "ID: " + id + "\nName: " + name + "\nPrice: $" + price + "\nDescription: " + description; + } + +} + + diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/ProductCatalogService.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/ProductCatalogService.java new file mode 100644 index 000000000000..eecffe21d9d7 --- /dev/null +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/ProductCatalogService.java @@ -0,0 +1,42 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; +import java.util.List; + +/** + * The type Product catalog service. + */ +public class ProductCatalogService { + private List products; + + /** + * Instantiates a new Product catalog service. + * + * @param products the products + */ + public ProductCatalogService(List products) { + this.products = products; + } +} diff --git a/session-facade/src/main/java/com/iluwatar/sessionfacade/ShoppingFacade.java b/session-facade/src/main/java/com/iluwatar/sessionfacade/ShoppingFacade.java new file mode 100644 index 000000000000..7f4ed63c885a --- /dev/null +++ b/session-facade/src/main/java/com/iluwatar/sessionfacade/ShoppingFacade.java @@ -0,0 +1,100 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; +import java.util.ArrayList; +import java.util.List; + +/** + * The type Shopping facade. + */ +public class ShoppingFacade { + /** + * The Product catalog. + */ + List productCatalog = new ArrayList<>(); + /** + * The Cart. + */ + List cart = new ArrayList<>(); + /** + * The Cart service. + */ + CartService cartService = new CartService(cart, productCatalog); + /** + * The Order service. + */ + OrderService orderService = new OrderService(cart); + /** + * The Payment service. + */ + PaymentService paymentService = new PaymentService(); + + /** + * Instantiates a new Shopping facade. + */ + public ShoppingFacade() { + productCatalog = new ArrayList<>(); + productCatalog.add(new Product(1, "Wireless Mouse", 25.99, "Ergonomic wireless mouse with USB receiver.")); + productCatalog.add(new Product(2, "Gaming Keyboard", 79.99, "RGB mechanical gaming keyboard with programmable keys.")); + cart = new ArrayList<>(); + cartService = new CartService(cart, productCatalog); + orderService = new OrderService(cart); + paymentService = new PaymentService(); + } + + /** + * Add to cart. + * + * @param productId the product id + */ + public void addToCart(int productId) { + this.cartService.addToCart(productId); + } + + /** + * Remove from cart. + * + * @param productId the product id + */ + public void removeFromCart(int productId) { + this.cartService.removeFromCart(productId); + } + + /** + * Order. + */ + public void order() { + this.orderService.order(); + } + + /** + * Select payment method. + * + * @param method the method + */ + public void selectPaymentMethod(String method) { + this.paymentService.selectPaymentMethod(method); + } +} diff --git a/session-facade/src/test/java/com/iluwatar/sessionfacade/AppTest.java b/session-facade/src/test/java/com/iluwatar/sessionfacade/AppTest.java new file mode 100644 index 000000000000..012fcf4623ad --- /dev/null +++ b/session-facade/src/test/java/com/iluwatar/sessionfacade/AppTest.java @@ -0,0 +1,42 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +/** + * The type App test. + */ +public class AppTest { + + /** + * Should execute application without exception. + */ + @org.junit.jupiter.api.Test + void shouldExecuteApplicationWithoutException() { + assertDoesNotThrow(() -> App.main(new String[]{})); + } + +} diff --git a/session-facade/src/test/java/com/iluwatar/sessionfacade/CartServiceTest.java b/session-facade/src/test/java/com/iluwatar/sessionfacade/CartServiceTest.java new file mode 100644 index 000000000000..ca9cf4479bb5 --- /dev/null +++ b/session-facade/src/test/java/com/iluwatar/sessionfacade/CartServiceTest.java @@ -0,0 +1,94 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import lombok.extern.slf4j.Slf4j; +import org.mockito.MockitoAnnotations; +import java.util.ArrayList; +import java.util.List; + +/** + * The type Cart service test. + */ +@Slf4j +class CartServiceTest { + + private CartService cartService; + private List cart; + + /** + * Sets up. + */ + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + cart = new ArrayList<>(); + List productCatalog = new ArrayList<>(); + productCatalog.add(new Product(1, "Product A", 2.0, "any description")); + productCatalog.add(new Product(2, "Product B", 300.0, "a watch")); + cartService = new CartService(cart, productCatalog); + } + + /** + * Test add to cart. + */ + @Test + void testAddToCart() { + cartService.addToCart(1); + assertEquals(1, cart.size()); + assertEquals("Product A", cart.get(0).name()); + } + + /** + * Test remove from cart. + */ + @Test + void testRemoveFromCart() { + cartService.addToCart(1); + assertEquals(1, cart.size()); + cartService.removeFromCart(1); + assertTrue(cart.isEmpty()); + } + + /** + * Test add to cart with invalid product id. + */ + @Test + void testAddToCartWithInvalidProductId() { + cartService.addToCart(999); + assertTrue(cart.isEmpty()); + } + + /** + * Test remove from cart with invalid product id. + */ + @Test + void testRemoveFromCartWithInvalidProductId() { + cartService.removeFromCart(999); + assertTrue(cart.isEmpty()); + } +} diff --git a/session-facade/src/test/java/com/iluwatar/sessionfacade/PaymentServiceTest.java b/session-facade/src/test/java/com/iluwatar/sessionfacade/PaymentServiceTest.java new file mode 100644 index 000000000000..35daacced5b3 --- /dev/null +++ b/session-facade/src/test/java/com/iluwatar/sessionfacade/PaymentServiceTest.java @@ -0,0 +1,62 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; +import static org.mockito.Mockito.*; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; + +class PaymentServiceTest { + private PaymentService paymentService; + private Logger mockLogger; + + @BeforeEach + void setUp() { + paymentService = new PaymentService(); + mockLogger = mock(Logger.class); + paymentService.LOGGER = mockLogger; + } + + @Test + void testSelectCashPaymentMethod() { + String method = "cash"; + paymentService.selectPaymentMethod(method); + verify(mockLogger).info("Client have chosen cash payment option"); + } + + @Test + void testSelectCreditCardPaymentMethod() { + String method = "credit"; + paymentService.selectPaymentMethod(method); + verify(mockLogger).info("Client have chosen credit card payment option"); + } + + @Test + void testSelectUnspecifiedPaymentMethod() { + String method = "cheque"; + paymentService.selectPaymentMethod(method); + verify(mockLogger).info("Unspecified payment method type"); + } +} diff --git a/session-facade/src/test/java/com/iluwatar/sessionfacade/ProductTest.java b/session-facade/src/test/java/com/iluwatar/sessionfacade/ProductTest.java new file mode 100644 index 000000000000..2d664698551f --- /dev/null +++ b/session-facade/src/test/java/com/iluwatar/sessionfacade/ProductTest.java @@ -0,0 +1,77 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * The type Product test. + */ +public class ProductTest { + /** + * Test product creation. + */ + @Test + public void testProductCreation() { + int id = 1; + String name = "Product A"; + double price = 200.0; + String description = "a description"; + Product product = new Product(id,name,price,description); + assertEquals(id, product.id()); + assertEquals(name, product.name()); + assertEquals(price, product.price()); + assertEquals(description, product.description()); + } + + /** + * Test equals and hash code. + */ + @Test + public void testEqualsAndHashCode() { + Product product1 = new Product(1, "Product A", 99.99, "a description"); + Product product2 = new Product(1, "Product A", 99.99, "a description"); + Product product3 = new Product(2, "Product B", 199.99, "a description"); + + assertEquals(product1, product2); + assertNotEquals(product1, product3); + assertEquals(product1.hashCode(), product2.hashCode()); + assertNotEquals(product1.hashCode(), product3.hashCode()); + } + + /** + * Test to string. + */ + @Test + public void testToString() { + Product product = new Product(1, "Product A", 99.99, "a description"); + String toStringResult = product.toString(); + assertTrue(toStringResult.contains("Product A")); + assertTrue(toStringResult.contains("99.99")); + } + +} diff --git a/session-facade/src/test/java/com/iluwatar/sessionfacade/ShoppingFacadeTest.java b/session-facade/src/test/java/com/iluwatar/sessionfacade/ShoppingFacadeTest.java new file mode 100644 index 000000000000..75c84beb12b2 --- /dev/null +++ b/session-facade/src/test/java/com/iluwatar/sessionfacade/ShoppingFacadeTest.java @@ -0,0 +1,74 @@ +/* + * This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt). + * + * The MIT License + * Copyright © 2014-2022 Ilkka Seppälä + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.iluwatar.sessionfacade; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Unit tests for ShoppingFacade. + */ +class ShoppingFacadeTest { + + private ShoppingFacade shoppingFacade; + + @BeforeEach + void setUp() { + shoppingFacade = new ShoppingFacade(); + } + + @Test + void testAddToCart() { + shoppingFacade.addToCart(1); + shoppingFacade.addToCart(2); + List cart = shoppingFacade.cart; + assertEquals(2, cart.size(), "Cart should contain two items."); + assertEquals("Wireless Mouse", cart.get(0).name(), "First item in the cart should be 'Wireless Mouse'."); + assertEquals("Gaming Keyboard", cart.get(1).name(), "Second item in the cart should be 'Gaming Keyboard'."); + } + + @Test + void testRemoveFromCart() { + shoppingFacade.addToCart(1); + shoppingFacade.addToCart(2); + shoppingFacade.removeFromCart(1); + List cart = shoppingFacade.cart; + assertEquals(1, cart.size(), "Cart should contain one item after removal."); + assertEquals("Gaming Keyboard", cart.get(0).name(), "Remaining item should be 'Gaming Keyboard'."); + } + + @Test + void testOrder() { + shoppingFacade.addToCart(1); + shoppingFacade.addToCart(2); + shoppingFacade.order(); + assertTrue(shoppingFacade.cart.isEmpty(), "Cart should be empty after placing the order."); + } +}