|
| 1 | +# The facade pattern |
| 2 | + |
| 3 | +## Purpose |
| 4 | + |
| 5 | +The facade pattern allows us to create a simple interface around complex |
| 6 | +operations. The facade might provide less granular control of the underlying |
| 7 | +system, but in return it can be much faster and simpler to work with. |
| 8 | + |
| 9 | +Suppose we have a smart home with lots of devices, and we want a simple way of |
| 10 | +activating "holiday mode". There are a few things we need to do with our |
| 11 | +different devices which would be tedious for the users to do one by one. We can |
| 12 | +solve this by adding a facade - which in this case is a single `.holidayMode()` |
| 13 | +method. |
| 14 | + |
| 15 | +## Implementation |
| 16 | + |
| 17 | +Suppose our `SmartHome` class keeps track of various devices such as cameras, |
| 18 | +lights, and thermostats. Each device type has specific behaviors. |
| 19 | + |
| 20 | +::: code-group |
| 21 | + |
| 22 | +```java [SmartDevice.java] |
| 23 | +public abstract class SmartDevice { |
| 24 | + protected String type; |
| 25 | + |
| 26 | + public String getType() { |
| 27 | + return type; |
| 28 | + } |
| 29 | +} |
| 30 | +``` |
| 31 | + |
| 32 | +```java [SmartCamera.java] |
| 33 | +public class SmartCamera extends SmartDevice { |
| 34 | + private boolean isOn; |
| 35 | + |
| 36 | + public SmartCamera() { |
| 37 | + this.type = "camera"; |
| 38 | + this.isOn = false; // Off by default |
| 39 | + } |
| 40 | + |
| 41 | + public boolean isOn() { |
| 42 | + return isOn; |
| 43 | + } |
| 44 | + |
| 45 | + public void togglePower() { |
| 46 | + isOn = !isOn; |
| 47 | + } |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +```java [SmartLight.java] |
| 52 | +public class SmartLight extends SmartDevice { |
| 53 | + private boolean isOn; |
| 54 | + |
| 55 | + public SmartLight() { |
| 56 | + this.type = "light"; |
| 57 | + this.isOn = false; // Off by default |
| 58 | + } |
| 59 | + |
| 60 | + public boolean isOn() { |
| 61 | + return isOn; |
| 62 | + } |
| 63 | + |
| 64 | + public void togglePower() { |
| 65 | + isOn = !isOn; |
| 66 | + } |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +```java |
| 71 | +public class SmartThermostat extends SmartDevice { |
| 72 | + private int temperature; |
| 73 | + |
| 74 | + public SmartThermostat() { |
| 75 | + this.type = "thermostat"; |
| 76 | + this.temperature = 20; // Default temperature |
| 77 | + } |
| 78 | + |
| 79 | + public void setTemperature(int temp) { |
| 80 | + this.temperature = temp; |
| 81 | + } |
| 82 | + |
| 83 | + public int getTemperature() { |
| 84 | + return temperature; |
| 85 | + } |
| 86 | +} |
| 87 | +``` |
| 88 | + |
| 89 | +::: |
| 90 | + |
| 91 | +For "holiday mode", we want |
| 92 | + |
| 93 | +- all cameras to be on |
| 94 | +- all lights to be off |
| 95 | +- all thermostats set to 5 |
| 96 | + |
| 97 | +We can create a facade within the `SmartHome` class to help with this. |
| 98 | + |
| 99 | +```java |
| 100 | +import java.util.ArrayList; |
| 101 | +import java.util.List; |
| 102 | +import java.util.stream.Collectors; |
| 103 | + |
| 104 | +public class SmartHome { |
| 105 | + private List<SmartDevice> devices; |
| 106 | + |
| 107 | + public SmartHome() { |
| 108 | + devices = new ArrayList<>(); |
| 109 | + } |
| 110 | + |
| 111 | + // Method to add devices to the SmartHome |
| 112 | + public void addDevice(SmartDevice device) { |
| 113 | + devices.add(device); |
| 114 | + } |
| 115 | + |
| 116 | + // Facade method to activate holiday mode |
| 117 | + public void holidayMode() { |
| 118 | + // Turn on all cameras |
| 119 | + for (SmartDevice device : getDevicesByType("camera")) { |
| 120 | + if (device instanceof SmartCamera) { |
| 121 | + SmartCamera camera = (SmartCamera) device; |
| 122 | + if (!camera.isOn()) { |
| 123 | + camera.togglePower(); |
| 124 | + } |
| 125 | + } |
| 126 | + } |
| 127 | + |
| 128 | + // Turn off all lights |
| 129 | + for (SmartDevice device : getDevicesByType("light")) { |
| 130 | + if (device instanceof SmartLight) { |
| 131 | + SmartLight light = (SmartLight) device; |
| 132 | + if (light.isOn()) { |
| 133 | + light.togglePower(); |
| 134 | + } |
| 135 | + } |
| 136 | + } |
| 137 | + |
| 138 | + // Set all thermostats to 5 degrees |
| 139 | + for (SmartDevice device : getDevicesByType("thermostat")) { |
| 140 | + if (device instanceof SmartThermostat) { |
| 141 | + SmartThermostat thermostat = (SmartThermostat) device; |
| 142 | + thermostat.setTemperature(5); |
| 143 | + } |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + // Helper method to retrieve devices by type |
| 148 | + private List<SmartDevice> getDevicesByType(String type) { |
| 149 | + return devices.stream() |
| 150 | + .filter(device -> device.getType().equals(type)) |
| 151 | + .collect(Collectors.toList()); |
| 152 | + } |
| 153 | +} |
| 154 | +``` |
| 155 | + |
| 156 | +## Usage |
| 157 | + |
| 158 | +Now, instead of having our users go and configure all of these settings |
| 159 | +themselves, we can show them a button which calls holiday mode: |
| 160 | + |
| 161 | +::: code-group |
| 162 | + |
| 163 | +```java |
| 164 | +public class Main { |
| 165 | + public static void main(String[] args) { |
| 166 | + SmartHome smartHome = new SmartHome(); |
| 167 | + |
| 168 | + // Creating devices |
| 169 | + SmartCamera camera1 = new SmartCamera(); |
| 170 | + SmartCamera camera2 = new SmartCamera(); |
| 171 | + SmartLight light1 = new SmartLight(); |
| 172 | + SmartLight light2 = new SmartLight(); |
| 173 | + SmartThermostat thermostat1 = new SmartThermostat(); |
| 174 | + SmartThermostat thermostat2 = new SmartThermostat(); |
| 175 | + |
| 176 | + // Adding devices to the smart home |
| 177 | + smartHome.addDevice(camera1); |
| 178 | + smartHome.addDevice(camera2); |
| 179 | + smartHome.addDevice(light1); |
| 180 | + smartHome.addDevice(light2); |
| 181 | + smartHome.addDevice(thermostat1); |
| 182 | + smartHome.addDevice(thermostat2); |
| 183 | + |
| 184 | + // Simulating device states before holiday mode |
| 185 | + light1.togglePower(); // Turn on light1 |
| 186 | + thermostat1.setTemperature(22); // Set thermostat1 to 22 degrees |
| 187 | + |
| 188 | + // Activating holiday mode |
| 189 | + smartHome.holidayMode(); |
| 190 | + |
| 191 | + // Checking the state of devices after holiday mode |
| 192 | + System.out.println("Camera1 is on: " + camera1.isOn()); |
| 193 | + System.out.println("Camera2 is on: " + camera2.isOn()); |
| 194 | + System.out.println("Light1 is on: " + light1.isOn()); |
| 195 | + System.out.println("Light2 is on: " + light2.isOn()); |
| 196 | + System.out.println("Thermostat1 temperature: " + thermostat1.getTemperature()); |
| 197 | + System.out.println("Thermostat2 temperature: " + thermostat2.getTemperature()); |
| 198 | + } |
| 199 | +} |
| 200 | +``` |
| 201 | + |
| 202 | +```conole [output] |
| 203 | +Camera1 is on: true |
| 204 | +Camera2 is on: true |
| 205 | +Light1 is on: false |
| 206 | +Light2 is on: false |
| 207 | +Thermostat1 temperature: 5 |
| 208 | +Thermostat2 temperature: 5 |
| 209 | +``` |
| 210 | + |
| 211 | +::: |
| 212 | + |
| 213 | +The user has less overall control, but a much more convenient interface. |
0 commit comments