Backend Development 12 min read

Facade Design Pattern with Spring Boot Example

The article explains the Facade design pattern and demonstrates its use in a Spring Boot travel‑booking application, where a BookingFacade aggregates FlightService, HotelService, and PackageService to provide a single bookTravel method that a REST controller calls, simplifying the API and reducing coupling.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Facade Design Pattern with Spring Boot Example

The Facade Pattern is a structural design pattern that offers a simplified interface to a complex subsystem, similar to a remote control that hides internal workings.

In code, a Facade class aggregates multiple subsystem objects and provides a single method such as operation() for clients, thereby reducing coupling and improving maintainability.

Key advantages include a simplified API, lower coupling between client and subsystems, easier maintenance, and straightforward extensibility.

Practical example: an online travel booking system involves flight, hotel, and package services. A BookingFacade encapsulates these services, allowing a controller to call one method to complete the whole booking flow.

Project dependencies (Maven):

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- H2 Database (for simplicity) -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Domain entities:

@Entity
public class Flight {
    @Id
    private Long id;
    private String flightNumber;
    private String departure;
    private String arrival;
    // Getters and Setters
}

@Entity
public class Hotel {
    @Id
    private Long id;
    private String name;
    private String location;
    // Getters and Setters
}

@Entity
public class TourPackage {
    @Id
    private Long id;
    private String name;
    private String destination;
    // Getters and Setters
}

Subsystem services:

@Service
public class FlightService {
    public List<Flight> findAvailableFlights(String departure, String arrival, LocalDate date) {
        System.out.println("Query flights: " + departure + " to " + arrival + " on " + date);
        return List.of(new Flight(1L, "AA123", departure, arrival));
    }
}

@Service
public class HotelService {
    public List<Hotel> findAvailableHotels(String location, LocalDate checkIn, LocalDate checkOut) {
        System.out.println("Query hotels: " + location + " from " + checkIn + " to " + checkOut);
        return List.of(new Hotel(1L, "Hotel California", location));
    }
}

@Service
public class PackageService {
    public List<TourPackage> recommendPackages(String destination) {
        System.out.println("Recommend packages for: " + destination);
        return List.of(new TourPackage(1L, "Paris Special", destination));
    }
}

Facade that coordinates the subsystems:

@Service
public class BookingFacade {
    private final FlightService flightService;
    private final HotelService hotelService;
    private final PackageService packageService;

    public BookingFacade(FlightService flightService, HotelService hotelService, PackageService packageService) {
        this.flightService = flightService;
        this.hotelService = hotelService;
        this.packageService = packageService;
    }

    public boolean bookTravel(String departure, String arrival, LocalDate flightDate,
                              String hotelLocation, LocalDate checkIn, LocalDate checkOut,
                              String destination) {
        List<Flight> flights = flightService.findAvailableFlights(departure, arrival, flightDate);
        if (flights.isEmpty()) return false;
        List<Hotel> hotels = hotelService.findAvailableHotels(hotelLocation, checkIn, checkOut);
        if (hotels.isEmpty()) return false;
        List<TourPackage> packages = packageService.recommendPackages(destination);
        if (packages.isEmpty()) return false;
        return true;
    }
}

Controller using the Facade:

@RestController
@RequestMapping("/bookings")
public class BookingController {
    private final BookingFacade bookingFacade;

    public BookingController(BookingFacade bookingFacade) {
        this.bookingFacade = bookingFacade;
    }

    @PostMapping
    public ResponseEntity<String> bookTravel(@RequestBody TravelRequest travelRequest) {
        boolean success = bookingFacade.bookTravel(
                travelRequest.getDeparture(),
                travelRequest.getArrival(),
                travelRequest.getFlightDate(),
                travelRequest.getHotelLocation(),
                travelRequest.getCheckIn(),
                travelRequest.getCheckOut(),
                travelRequest.getDestination());
        if (success) {
            return ResponseEntity.ok("Travel booking succeeded");
        }
        return ResponseEntity.badRequest().body("Travel booking failed");
    }
}

The UML class diagram (not shown) illustrates how the Facade interacts with multiple subsystem classes, providing a high‑level interface to clients.

Design PatternsJavaSoftware ArchitectureSpring BootFacade Pattern
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.