Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
274 changes: 274 additions & 0 deletions remote-facade/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
---
title: "Remote Facade Pattern in Java: Simplifying Distributed System Interfaces"
shortTitle: Remote Facade
description: "Learn how to implement the Remote Facade Design Pattern in Java to provide a coarse-grained interface to a set of fine-grained objects in a distributed system. Improve performance and encapsulate complexities with practical examples."
category: Architectural
language: en
tag:
- Abstraction
- API design
- Client-server
- Code simplification
- Decoupling
- Distributed systems
- Encapsulation
- Interface
- Performance optimization
- Remote communication
---

## Intent of Remote Facade Design Pattern

The Remote Facade Design Pattern provides a coarse-grained interface to a set of fine-grained objects in a distributed system. This pattern helps to reduce the number of remote calls, thus improving performance and encapsulating the complexities of interactions between remote objects.

## Detailed Explanation of Remote Facade Pattern with Real-World Examples

Real-world example

> Imagine an e-commerce system where the product catalog, inventory management, and order processing are implemented as separate services. Each service has its own fine-grained API with numerous methods. To simplify the interaction for remote clients (like mobile apps or third-party integrations), a Remote Facade is provided. This facade offers a simplified API that combines multiple operations into single calls. For example, instead of making separate calls to check product availability, get pricing, and place an order, a client can make a single "purchase product" call to the Remote Facade, which internally coordinates all the necessary operations.

In plain words

> Remote Facade pattern provides a simplified, coarse-grained interface to a set of fine-grained objects in a distributed system, reducing the number of remote calls and improving performance.

Wikipedia says

> A remote facade is a design pattern in software engineering that provides a coarse-grained facade on fine-grained objects to improve efficiency over a network.

## Programmatic Example of Remote Facade Pattern in Java

Here's an example of the Remote Facade Design Pattern in a product inventory system, demonstrating how a Java remote facade can streamline complex operations in a distributed environment.

First, we have the Data Transfer Object (DTO) that will be used to transfer data between the client and server:

```java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class ProductDto {
private String name;
private double price;
private int stock;

@Override
public String toString() {
return String.format("Product[name=%s, price=%.2f, stock=%d]", name, price, stock);
}
}
```

Then we have the server-side domain model:

```java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
private String name;
private double price;
private int stock;
}
```

The server-side service layer consists of fine-grained services:

```java
@Slf4j
public class ProductService {
private final Map<String, Product> products = new HashMap<>();

public boolean addProduct(String name, double price, int stock) {
if (products.containsKey(name)) {
LOGGER.info("Product {} already exists", name);
return false;
}

products.put(name, new Product(name, price, stock));
LOGGER.info("Product {} added with price {} and stock {}", name, price, stock);
return true;
}

public Optional<Product> getProduct(String name) {
var product = products.get(name);
if (product == null) {
LOGGER.info("Product {} not found", name);
return Optional.empty();
}

LOGGER.info("Retrieved product {}: price={}, stock={}",
name, product.getPrice(), product.getStock());
return Optional.of(product);
}

// Other methods for updating price, stock, etc.
}

@Slf4j
public class OrderService {
private final ProductService productService;

public OrderService(ProductService productService) {
this.productService = productService;
}

public boolean processOrder(String productName, int quantity) {
LOGGER.info("Processing order for {} units of product {}", quantity, productName);

// Check if the product exists and has enough stock
var productOpt = productService.getProduct(productName);
if (productOpt.isEmpty()) {
LOGGER.info("Order processing failed: Product {} not found", productName);
return false;
}

// Decrease the stock and process the order
// ...

return true;
}
}
```

The Remote Facade interface provides a coarse-grained interface to these services:

```java
public interface ProductRemoteFacade {
boolean addProduct(String name, double price, int stock);
Optional<ProductDto> getProductDetails(String name);
boolean updateProductPrice(String name, double price);
boolean updateProductStock(String name, int stock);
boolean processOrder(String productName, int quantity);
}
```

The implementation of the Remote Facade coordinates the fine-grained services:

```java
@Slf4j
public class ProductRemoteFacadeImpl implements ProductRemoteFacade {
private final ProductService productService;
private final OrderService orderService;

public ProductRemoteFacadeImpl(ProductService productService, OrderService orderService) {
this.productService = productService;
this.orderService = orderService;
}

@Override
public boolean addProduct(String name, double price, int stock) {
LOGGER.info("Remote facade: Adding product {}", name);
return productService.addProduct(name, price, stock);
}

@Override
public Optional<ProductDto> getProductDetails(String name) {
LOGGER.info("Remote facade: Getting details for product {}", name);
return productService.getProduct(name)
.map(this::convertToDto);
}

// Other methods that coordinate the fine-grained services

private ProductDto convertToDto(Product product) {
return new ProductDto(product.getName(), product.getPrice(), product.getStock());
}
}
```

The client uses the Remote Facade to interact with the server:

```java
@Slf4j
public class Client {
private final ProductRemoteFacade remoteFacade;

public Client(ProductRemoteFacade remoteFacade) {
this.remoteFacade = remoteFacade;
}

public void addProduct(String name, double price, int stock) {
LOGGER.info("Client: Adding product {}", name);
boolean success = remoteFacade.addProduct(name, price, stock);
if (success) {
LOGGER.info("Client: Product {} added successfully", name);
} else {
LOGGER.info("Client: Failed to add product {}", name);
}
}

// Other methods that use the remote facade
}
```

Now let's use the Remote Facade pattern:

```java
public static void main(String[] args) {
// Start the server
var server = new Server();
server.start();

// Create a client
var client = new Client(server.getRemoteFacade());

// Perform operations using the remote facade
client.addProduct("Laptop", 1200.00, 10);
client.getProductDetails("Laptop");
client.updateProductPrice("Laptop", 1250.00);
client.processOrder("Laptop", 2);

// Stop the server
server.stop();
}
```

## When to Use the Remote Facade Pattern in Java

Use the Remote Facade pattern in Java when:

* You need to provide a simplified interface to a complex subsystem in a distributed environment.
* You want to reduce the number of remote calls between client and server to improve performance.
* You need to encapsulate the complexities of interactions between remote objects.
* You want to provide a coarse-grained API that aggregates multiple fine-grained operations.
* You need to transfer data between client and server using DTOs to reduce network traffic.

## Remote Facade Pattern Java Tutorials

* [Remote Facade (Martin Fowler)](https://martinfowler.com/eaaCatalog/remoteFacade.html)
* [Remote Facade vs. Facade Pattern (StackOverflow)](https://stackoverflow.com/questions/20527419/remote-facade-pattern-vs-facade-pattern)
* [Patterns of Enterprise Application Architecture (Google Books)](https://books.google.fi/books?id=vqTfNFDzzdIC&pg=PA303#v=onepage&q&f=false)

## Real-World Applications of Remote Facade Pattern in Java

* Enterprise JavaBeans (EJB) Session Beans often act as remote facades to provide a coarse-grained interface to business logic.
* RESTful web services frequently implement the Remote Facade pattern to provide a simplified API to complex backend systems.
* Microservices architectures use API Gateways as remote facades to aggregate multiple service calls into a single client-facing API.

## Benefits and Trade-offs of Remote Facade Pattern

Benefits:

* Reduces the number of remote calls, improving performance in distributed systems.
* Simplifies the client-side code by providing a coarse-grained interface.
* Encapsulates the complexities of interactions between remote objects.
* Improves maintainability by centralizing the remote communication logic.
* Reduces network traffic by aggregating multiple operations into single calls.

Trade-offs:

* Adds an additional layer to the architecture, which can increase complexity.
* May lead to a less flexible API if not designed carefully.
* Can become a bottleneck if not properly optimized.
* Requires careful design of DTOs to balance between data transfer efficiency and usability.

## Related Java Design Patterns

* [Facade](https://java-design-patterns.com/patterns/facade/): While the standard Facade pattern simplifies a complex subsystem, Remote Facade specifically addresses the challenges of distributed systems.
* [Data Transfer Object](https://java-design-patterns.com/patterns/data-transfer-object/): Often used with Remote Facade to transfer data between client and server.
* [Service Layer](https://java-design-patterns.com/patterns/service-layer/): Remote Facade often sits on top of a Service Layer to provide remote access to business logic.

## References and Credits

* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3QbO7qN)
* [Patterns of Enterprise Application Architecture by Martin Fowler](https://amzn.to/4cGk2Jz)
* [Enterprise Integration Patterns](https://amzn.to/3UpTLrG)
70 changes: 70 additions & 0 deletions remote-facade/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

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.

-->
<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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.iluwatar</groupId>
<artifactId>java-design-patterns</artifactId>
<version>1.26.0-SNAPSHOT</version>
</parent>
<artifactId>remote-facade</artifactId>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.remotefacade.App</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Loading
Loading