Facade Design Pattern

A Facade design pattern is a structural concept that helps reduce complexity between clients and subsystems by providing a higher-level interface known as a facade.

Design Patterns: Elements of Reusable Object-Oriented Software

image from Design Patterns: Elements of Reusable Object-Oriented Software

For instance, consider an e-commerce web application server that has subsystem services such as InventoryService, PaymentService, and ShippingService. If each client had access to each service, the subsystem classes’ will be tightly coupled with the client. To decouple the two and reduce complexity, a facade class or interface can be introduced as a liaison between the two. Clients can be agnostic to the implementation of the subsystem and the subsystem can just concentrate on the implementation of its logic.

Sample Code

Domain

data class Product(
  val productId : Int,
  val name : String,
)

Client/Controller

class Controller(
  val facade : OrderServiceFacade
){
  fun orderProduct(productId : Int) : Boolean {
    val isOrderComplete = facade.placeOrder(productId)
    return isOrderComplete
  }
}

Facade

interface OrderServiceFacade {
  fun placeOrder(productId : Int) : Boolean
}

class OrderServiceFacadeImpl(
  val inventoryService : InventoryService,
  val paymentService : PaymentService,
  val shippingService : ShippingService
) : OrderServiceFacade(){
  override fun placeOrder(productId : Int) : Boolean {
    return if(val product = inventoryService.isAvailable(productId)){
      val paymentConfirmed = paymentService.makePayment()
      if(paymentConfirmed){
        shippingService.shipProduct(product)
        true
      } else false
    } else false
  }
}

Service/Subsystem

class InventoryService {
  fun isAvailable (productId : Int) : Product {
    /* Check persistent data to see if inventory is available */
    return product
  }
}

class PaymentService {
  fun makePayment () : Boolean {
    /* Connect with payment such as payment gateway or in app purchase */
    return true / false
  }
}

class ShippingServicxe{
  fun shipProduct(product : Product) : Unit {
    /* connect with external shipment service to ship product */
  }
}