Facade Design Pattern

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);
    }
}

follow us on