The Facade Design Pattern
is part of the Gang of Four Design Patterns
and one of the Structural Design Patterns
. it adds a Wrapper Class
to hide the implementation and allows decoupling
. it's a helper class
, it doesn't restrict users to directly using the underlying method, and usage of the Facade
is purely optional.
Facade Design Pattern
hides or encapsulates
the complexity of the system and provides a simple and easy interface
with all the functionality. hence in the future, if required the functionality can be changed later without affecting the Interface.
Some real-world examples of Facade Design Patterns are
A dinner ordering food in a restaurant has a very simple interface
or menu cards or facades, they don't know how the food is prepared and by whom.
An e-commerce
portal provides a very simple User Interface
to place an order, in the backend, a lot of processes happen such as Warehouse Management
, Packaging
, Delivery
, Supply
, Taxes
, etc.
an Apple Salad
requires a lot of steps, a customer in a restaurant just orders an apple salad. the background complexity is abstracted by the facade
.
package org.wesome.design.patterns;
import java.util.List;
public interface AppleSalad {
String STEP_1 = "wash the ";
String STEP_2 = "cut in small pieces";
String STEP_3 = "add seasoning spices in the ";
List<String> prepareApple(List<String> steps);
List<String> cutInPieces(List<String> steps);
List<String> seasoningSpices(List<String> steps);
}
package org.wesome.design.patterns;
import java.util.ArrayList;
import java.util.List;
public class SaladFacade {
public static List<String> orderSalad(Apple apple) {
List<String> steps = new ArrayList<>();
AppleSalad appleSalad;
switch (apple) {
case MACINTOSH:
appleSalad = new MacintoshFacade();
appleSalad.prepareApple(steps);
appleSalad.cutInPieces(steps);
appleSalad.seasoningSpices(steps);
break;
case FUJI:
appleSalad = new FujiFacade();
appleSalad.prepareApple(steps);
appleSalad.cutInPieces(steps);
appleSalad.seasoningSpices(steps);
break;
}
return steps;
}
}
package org.wesome.design.patterns;
public enum Apple {
MACINTOSH, FUJI
}
package org.wesome.design.patterns;
import java.util.List;
import static org.wesome.design.patterns.Apple.FUJI;
public class FujiFacade implements AppleSalad {
@Override
public List<String> prepareApple(List<String> steps) {
steps.add(STEP_1 + FUJI);
return steps;
}
@Override
public List<String> cutInPieces(List<String> steps) {
steps.add(STEP_2);
return steps;
}
@Override
public List<String> seasoningSpices(List<String> steps) {
steps.add(STEP_3 + FUJI);
return steps;
}
}
package org.wesome.design.patterns;
import java.util.List;
import static org.wesome.design.patterns.Apple.MACINTOSH;
public class MacintoshFacade implements AppleSalad {
@Override
public List<String> prepareApple(List<String> steps) {
steps.add(STEP_1 + MACINTOSH);
return steps;
}
@Override
public List<String> cutInPieces(List<String> steps) {
steps.add(STEP_2);
return steps;
}
@Override
public List<String> seasoningSpices(List<String> steps) {
steps.add(STEP_3 + MACINTOSH);
return steps;
}
}
package org.wesome.design.patterns;
import java.util.List;
import static org.wesome.design.patterns.Apple.FUJI;
import static org.wesome.design.patterns.Apple.MACINTOSH;
import static org.wesome.design.patterns.SaladFacade.orderSalad;
public class Facade {
public static void main(String[] args) {
List<String> steps = orderSalad(MACINTOSH);
System.out.println("steps to prepare = " + MACINTOSH);
steps.forEach(System.out::println);
steps = orderSalad(FUJI);
System.out.println("steps to prepare = " + FUJI);
steps.forEach(System.out::println);
}
}
plugins {
id 'java'
id "io.freefair.lombok" version "6.2.0"
}
group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}
test {
useJUnitPlatform()
}
package org.wesome.design.patterns;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.wesome.design.patterns.Apple.FUJI;
import static org.wesome.design.patterns.Apple.MACINTOSH;
import static org.wesome.design.patterns.AppleSalad.*;
public class FacadeTest {
@Test
void testMacintoshFacade() {
SaladFacade.orderSalad(MACINTOSH);
List<String> actualSteps = SaladFacade.orderSalad(MACINTOSH);
List<String> expectedSteps = Arrays.asList(STEP_1 + MACINTOSH, STEP_2, STEP_3 + MACINTOSH);
Assertions.assertEquals(expectedSteps, actualSteps);
}
@Test
void testFujiFacade() {
List<String> actualSteps = SaladFacade.orderSalad(FUJI);
List<String> expectedSteps = Arrays.asList(STEP_1 + FUJI, STEP_2, STEP_3 + FUJI);
Assertions.assertEquals(expectedSteps, actualSteps);
}
}