diff --git a/patterns/facade/pom.xml b/patterns/facade/pom.xml
new file mode 100644
index 000000000000..ee46a2a80d79
--- /dev/null
+++ b/patterns/facade/pom.xml
@@ -0,0 +1,37 @@
+
+
+ 4.0.0
+ com.baeldung.pattern.facade
+ pattern.facade
+ 1.0
+ jar
+
+ com.baeldung.patterns
+ patterns-parent
+ 1.0.0-SNAPSHOT
+ ..
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.7.0
+
+
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
\ No newline at end of file
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/CarEngineFacade.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/CarEngineFacade.java
new file mode 100644
index 000000000000..91f9b797381b
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/CarEngineFacade.java
@@ -0,0 +1,32 @@
+package com.baeldung.pattern.facade;
+
+import com.baeldung.pattern.facade.carsystem.*;
+
+public class CarEngineFacade {
+ private static final Integer DEFAULT_COOLING_TEMP = 90;
+ private static final Integer MAX_ALLOWED_TEMP = 50;
+ private FuelInjector fuelInjector = new FuelInjector();
+ private AirFlowController airFlowController = new AirFlowController();
+ private Starter starter = new Starter();
+ private CoolingController coolingController = new CoolingController();
+ private CatalyticConverter catalyticConverter = new CatalyticConverter();
+
+ public void startEngine(){
+ fuelInjector.on();
+ airFlowController.takeAir();
+ fuelInjector.on();
+ fuelInjector.inject();
+ starter.start();
+ coolingController.setTemperatureUpperLimit(DEFAULT_COOLING_TEMP);
+ coolingController.run();
+ catalyticConverter.on();
+ }
+
+ public void stopEngine(){
+ fuelInjector.off();
+ catalyticConverter.off();
+ coolingController.cool(MAX_ALLOWED_TEMP);
+ coolingController.stop();
+ airFlowController.off();
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/AirFlowController.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/AirFlowController.java
new file mode 100644
index 000000000000..5ee846ea31cf
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/AirFlowController.java
@@ -0,0 +1,19 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AirFlowController {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AirFlowController.class);
+ private AirFlowMeter airFlowMeter = new AirFlowMeter();
+
+ public void takeAir() {
+ airFlowMeter.getMeasurements();
+ LOGGER.info("Air provided!");
+ }
+
+ public void off() {
+ LOGGER.info("Air controller switched off.");
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/AirFlowMeter.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/AirFlowMeter.java
new file mode 100644
index 000000000000..b47f9cfc4afb
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/AirFlowMeter.java
@@ -0,0 +1,13 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AirFlowMeter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AirFlowMeter.class);
+
+ public void getMeasurements() {
+ LOGGER.info("Getting air measurements...");
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/CatalyticConverter.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/CatalyticConverter.java
new file mode 100644
index 000000000000..7d637cd4440e
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/CatalyticConverter.java
@@ -0,0 +1,17 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CatalyticConverter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CatalyticConverter.class);
+
+ public void on() {
+ LOGGER.info("Catalytic Converter switched on!");
+ }
+
+ public void off() {
+ LOGGER.info("Catalytic Converter switched off!");
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/CoolingController.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/CoolingController.java
new file mode 100644
index 000000000000..ae556e685c87
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/CoolingController.java
@@ -0,0 +1,34 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CoolingController {
+ private static final Logger LOGGER = LoggerFactory.getLogger(CoolingController.class);
+ private static final Integer DEFAULT_RADIATOR_SPEED = 10;
+
+ private Integer temperatureUpperLimit;
+ private Radiator radiator = new Radiator();
+ private TemperatureSensor temperatureSensor = new TemperatureSensor();
+
+ public void setTemperatureUpperLimit(Integer temperatureUpperLimit) {
+ LOGGER.info("Setting temperature upper limit to {}", temperatureUpperLimit);
+ this.temperatureUpperLimit = temperatureUpperLimit;
+ }
+
+ public void run() {
+ LOGGER.info("Cooling Controller ready!");
+ radiator.setSpeed(DEFAULT_RADIATOR_SPEED);
+ }
+
+ public void cool(Integer maxAllowedTemp) {
+ LOGGER.info("Scheduled cooling with maximum allowed temperature {}", maxAllowedTemp);
+ temperatureSensor.getTemperature();
+ radiator.on();
+ }
+
+ public void stop() {
+ LOGGER.info("Stopping Cooling Controller...");
+ radiator.off();
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/FuelInjector.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/FuelInjector.java
new file mode 100644
index 000000000000..c7905745e408
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/FuelInjector.java
@@ -0,0 +1,23 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FuelInjector {
+ private static final Logger LOGGER = LoggerFactory.getLogger(FuelInjector.class);
+
+ private FuelPump fuelPump = new FuelPump();
+
+ public void on(){
+ LOGGER.info("Fuel injector ready to inject fuel.");
+ }
+
+ public void inject() {
+ fuelPump.pump();
+ LOGGER.info("Fuel injected.");
+ }
+
+ public void off() {
+ LOGGER.info("Stopping Fuel injector...");
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/FuelPump.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/FuelPump.java
new file mode 100644
index 000000000000..900358f8ffe2
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/FuelPump.java
@@ -0,0 +1,13 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FuelPump {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(FuelPump.class);
+
+ public void pump() {
+ LOGGER.info("Fuel Pump is pumping fuel...");
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/Radiator.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/Radiator.java
new file mode 100644
index 000000000000..6ca6cef9d9b2
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/Radiator.java
@@ -0,0 +1,21 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Radiator {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Radiator.class);
+
+ public void on(){
+ LOGGER.info("Radiator switched on!");
+ }
+
+ public void off(){
+ LOGGER.info("Radiator switched off!");
+ }
+
+ public void setSpeed(Integer speed){
+ LOGGER.info("Setting radiator speed to {}",speed);
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/Starter.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/Starter.java
new file mode 100644
index 000000000000..b1f45a0be8fa
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/Starter.java
@@ -0,0 +1,13 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Starter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Starter.class);
+
+ public void start() {
+ LOGGER.info("Starting...");
+ }
+}
diff --git a/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/TemperatureSensor.java b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/TemperatureSensor.java
new file mode 100644
index 000000000000..d6a94858b45a
--- /dev/null
+++ b/patterns/facade/src/main/java/com/baeldung/pattern/facade/carsystem/TemperatureSensor.java
@@ -0,0 +1,13 @@
+package com.baeldung.pattern.facade.carsystem;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TemperatureSensor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(TemperatureSensor.class);
+
+ public void getTemperature(){
+ LOGGER.info("Getting temperature from the sensor...");
+ }
+
+}
diff --git a/patterns/facade/src/test/java/com/baeldung/pattern/facade/CarEngineFacadeTest.java b/patterns/facade/src/test/java/com/baeldung/pattern/facade/CarEngineFacadeTest.java
new file mode 100644
index 000000000000..79c159319ddb
--- /dev/null
+++ b/patterns/facade/src/test/java/com/baeldung/pattern/facade/CarEngineFacadeTest.java
@@ -0,0 +1,85 @@
+package com.baeldung.pattern.facade;
+
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.AppenderBase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class CarEngineFacadeTest {
+
+
+ private InMemoryCustomTestAppender appender;
+
+
+ @Before
+ public void setUp() {
+ appender = new InMemoryCustomTestAppender();
+ }
+
+ @After
+ public void tearDown() {
+ appender.stop();
+ }
+
+
+ @Test
+ public void whenStartEngine_thenAllNecessaryActionsPerformed() {
+ CarEngineFacade carEngineFacade = new CarEngineFacade();
+ carEngineFacade.startEngine();
+ assertTrue(appender.logContains("Fuel injector ready to inject fuel."));
+ assertTrue(appender.logContains("Getting air measurements..."));
+ assertTrue(appender.logContains("Air provided!"));
+ assertTrue(appender.logContains("Fuel injector ready to inject fuel."));
+ assertTrue(appender.logContains("Fuel Pump is pumping fuel..."));
+ assertTrue(appender.logContains("Fuel injected."));
+ assertTrue(appender.logContains("Starting..."));
+ assertTrue(appender.logContains("Setting temperature upper limit to 90"));
+ assertTrue(appender.logContains("Cooling Controller ready!"));
+ assertTrue(appender.logContains("Setting radiator speed to 10"));
+ assertTrue(appender.logContains("Catalytic Converter switched on!"));
+ }
+
+
+ @Test
+ public void whenStopEngine_thenAllNecessaryActionsPerformed() {
+ CarEngineFacade carEngineFacade = new CarEngineFacade();
+ carEngineFacade.stopEngine();
+ assertTrue(appender.logContains("Stopping Fuel injector..."));
+ assertTrue(appender.logContains("Catalytic Converter switched off!"));
+ assertTrue(appender.logContains("Scheduled cooling with maximum allowed temperature 50"));
+ assertTrue(appender.logContains("Getting temperature from the sensor..."));
+ assertTrue(appender.logContains("Radiator switched on!"));
+ assertTrue(appender.logContains("Stopping Cooling Controller..."));
+ assertTrue(appender.logContains("Radiator switched off!"));
+ assertTrue(appender.logContains("Air controller switched off."));
+ }
+
+ private class InMemoryCustomTestAppender extends AppenderBase {
+
+ private List logs = new ArrayList<>();
+
+ public InMemoryCustomTestAppender() {
+ ((Logger) LoggerFactory.getLogger("root")).addAppender(this);
+ start();
+ }
+
+ @Override
+ protected void append(ILoggingEvent eventObject) {
+ logs.add(eventObject);
+ }
+
+ public boolean logContains(String message) {
+ return logs.stream().anyMatch(event -> event.getFormattedMessage().equals(message));
+ }
+ }
+
+
+}
\ No newline at end of file