Implement Java facades by shaping a narrow task-oriented subsystem entry point instead of exposing every collaborating service directly.
Facade: A simplified interface that coordinates a subsystem so most callers can use it without understanding every internal collaborator.
In Java, a facade often sits at an application boundary such as:
The facade should reflect the task the caller wants done:
1public interface CheckoutFacade {
2 CheckoutResult placeOrder(CheckoutCommand command);
3}
That is stronger than exposing five subsystem services and asking each caller to orchestrate them correctly.
1public final class DefaultCheckoutFacade implements CheckoutFacade {
2 private final InventoryService inventory;
3 private final PricingService pricing;
4 private final PaymentService payments;
5 private final OrderService orders;
6
7 public DefaultCheckoutFacade(
8 InventoryService inventory,
9 PricingService pricing,
10 PaymentService payments,
11 OrderService orders) {
12 this.inventory = inventory;
13 this.pricing = pricing;
14 this.payments = payments;
15 this.orders = orders;
16 }
17
18 @Override
19 public CheckoutResult placeOrder(CheckoutCommand command) {
20 inventory.reserve(command.items());
21 Money total = pricing.totalFor(command.items(), command.customerId());
22 PaymentReceipt receipt = payments.charge(command.paymentToken(), total);
23 return orders.create(command, total, receipt.reference());
24 }
25}
This facade owns sequencing and subsystem collaboration, but it does not replace the underlying services. It simply gives most callers one coherent entry point.
Avoid turning the facade into:
If every operation in the subsystem ends up on one facade, the boundary is probably too broad.
Facade is strong when it simplifies common use, not when it monopolizes all access for style reasons.