|
| 1 | +--- |
| 2 | +title: Facade Pattern |
| 3 | +created: 2025-07-31 |
| 4 | +tags: |
| 5 | + - structural |
| 6 | +--- |
| 7 | +## Definition |
| 8 | + |
| 9 | +The **Facade Pattern** provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use. |
| 10 | + |
| 11 | +--- |
| 12 | +## Real World Analogy |
| 13 | + |
| 14 | +Imagine you just visited an ATM machine to withdraw cash by simply using the ATM card. What do you do? You simply insert the ATM card into the machine, give some input to it like the ATM PIN, enter the amount you want to withdraw, and then you get the cash. Simple, right? Insert the card and get the cash. |
| 15 | + |
| 16 | +But it is not as simple as it looks. The entire process you see while withdrawing the cash is the **facade**. Behind the scenes, many services are running like a database, network, bank authentication server, amount dispenser, and logging system. The whole tedious process is being handled by the facade. |
| 17 | + |
| 18 | +Below is the figure showing how the complex ATM system comes together and forms the facade. |
| 19 | + |
| 20 | +![[facade_pattern.png]] |
| 21 | +_Example of the Facade Pattern using the Complex ATM System_ |
| 22 | + |
| 23 | +We are going to implement a facade for a **Movie System**. Without the facade, we need to manually turn on all the systems like: |
| 24 | +- Turn the Projector On |
| 25 | +- Open the Wide Screen |
| 26 | +- Set the Volume to 10 |
| 27 | +- Turn on the Music System |
| 28 | +- Play the Music System in Dolby Atmos |
| 29 | +- Load the Movie |
| 30 | +- Turn on the Popcorn Popper |
| 31 | + |
| 32 | +This is a tedious task. For every new movie, we need to repeat the above steps. By the time we finish, the mood for watching the movie might be gone. Then again, to stop everything, we have to do the same steps in reverse order. |
| 33 | + |
| 34 | +By implementing the **Facade Pattern**, we can simplify this to just one button. All systems will start and stop with a single call. Even if we change the internal complex systems, the facade remains unaffected. |
| 35 | + |
| 36 | +--- |
| 37 | +## Design |
| 38 | + |
| 39 | +```mermaid |
| 40 | +classDiagram |
| 41 | + %% Subsystem classes |
| 42 | + class Amplifier { |
| 43 | + } |
| 44 | +
|
| 45 | + class Tuner { |
| 46 | + } |
| 47 | +
|
| 48 | + class DvdPlayer { |
| 49 | + } |
| 50 | +
|
| 51 | + class Projector { |
| 52 | + } |
| 53 | +
|
| 54 | + class Screen { |
| 55 | + } |
| 56 | +
|
| 57 | + class TheaterLights { |
| 58 | + } |
| 59 | +
|
| 60 | + class PopcornPopper { |
| 61 | + } |
| 62 | +
|
| 63 | + %% Facade |
| 64 | + class HomeTheaterFacade { |
| 65 | + -amp Amplifier |
| 66 | + -tuner Tuner |
| 67 | + -dvd DvdPlayer |
| 68 | + -projector Projector |
| 69 | + -screen Screen |
| 70 | + -lights TheaterLights |
| 71 | + -popper PopcornPopper |
| 72 | + +watchMovie(movie String) void |
| 73 | + +endMovie() void |
| 74 | + } |
| 75 | +
|
| 76 | + %% Composition relationships |
| 77 | + HomeTheaterFacade *-- Amplifier |
| 78 | + HomeTheaterFacade *-- Tuner |
| 79 | + HomeTheaterFacade *-- DvdPlayer |
| 80 | + HomeTheaterFacade *-- Projector |
| 81 | + HomeTheaterFacade *-- Screen |
| 82 | + HomeTheaterFacade *-- TheaterLights |
| 83 | + HomeTheaterFacade *-- PopcornPopper |
| 84 | +``` |
| 85 | + |
| 86 | +_Class Diagram for HomeTheatreFacade_ |
| 87 | + The `HomeTheaterFacade` class acts as the facade. It connects all subsystem components like `Amplifier`, `Tuner`, `DvdPlayer`, `Projector`, `Screen`, `TheaterLights`, and `PopcornPopper`. It provides two main methods: `watchMovie()` to start the movie and `endMovie()` to shut everything down. |
| 88 | + |
| 89 | +--- |
| 90 | +## Implementation in Java |
| 91 | + |
| 92 | +Below is the Java implementation of the **Facade Pattern** for the home theater system. |
| 93 | + |
| 94 | +```java title="Amplifier.java" |
| 95 | +class Amplifier { |
| 96 | + public void on() { |
| 97 | + System.out.println("Amplifier on"); |
| 98 | + } |
| 99 | + |
| 100 | + public void off() { |
| 101 | + System.out.println("Amplifier off"); |
| 102 | + } |
| 103 | + |
| 104 | + public void setDvd() { |
| 105 | + System.out.println("Amplifier setting DVD input"); |
| 106 | + } |
| 107 | + |
| 108 | + public void setSurroundSound() { |
| 109 | + System.out.println("Amplifier surround sound on"); |
| 110 | + } |
| 111 | + |
| 112 | + public void setVolume(int level) { |
| 113 | + System.out.println("Amplifier volume set to " + level); |
| 114 | + } |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +The `Amplifier` class represents a subsystem component that controls audio settings. It can turn on/off, set the DVD input, enable surround sound, and adjust the volume. |
| 119 | + |
| 120 | +```java title="Tuner.java" |
| 121 | +class Tuner { |
| 122 | + public void on() { |
| 123 | + System.out.println("Tuner on"); |
| 124 | + } |
| 125 | + |
| 126 | + public void off() { |
| 127 | + System.out.println("Tuner off"); |
| 128 | + } |
| 129 | + |
| 130 | + public void setFrequency(double freq) { |
| 131 | + System.out.println("Tuner frequency set to " + freq); |
| 132 | + } |
| 133 | +} |
| 134 | +``` |
| 135 | + |
| 136 | +The `Tuner` class is another subsystem representing radio functionality. It can power on/off and set frequencies. |
| 137 | + |
| 138 | +```java title="DvdPlayer.java" |
| 139 | +class DvdPlayer { |
| 140 | + public void on() { |
| 141 | + System.out.println("DVD Player on"); |
| 142 | + } |
| 143 | + |
| 144 | + public void off() { |
| 145 | + System.out.println("DVD Player off"); |
| 146 | + } |
| 147 | + |
| 148 | + public void play(String movie) { |
| 149 | + System.out.println("DVD Player playing \"" + movie + "\""); |
| 150 | + } |
| 151 | + |
| 152 | + public void stop() { |
| 153 | + System.out.println("DVD Player stopped"); |
| 154 | + } |
| 155 | + |
| 156 | + public void eject() { |
| 157 | + System.out.println("DVD Player eject"); |
| 158 | + } |
| 159 | +} |
| 160 | +``` |
| 161 | + |
| 162 | +The `DvdPlayer` class handles playing movies. It can turn on/off, play a given movie, stop playback, and eject the disc. |
| 163 | + |
| 164 | +```java title="Projector.java" |
| 165 | +class Projector { |
| 166 | + public void on() { |
| 167 | + System.out.println("Projector on"); |
| 168 | + } |
| 169 | + |
| 170 | + public void off() { |
| 171 | + System.out.println("Projector off"); |
| 172 | + } |
| 173 | + |
| 174 | + public void wideScreenMode() { |
| 175 | + System.out.println("Projector in widescreen mode"); |
| 176 | + } |
| 177 | +} |
| 178 | +``` |
| 179 | + |
| 180 | +The `Projector` represents the visual display. It can turn on/off and switch to widescreen mode. |
| 181 | + |
| 182 | +```java title="TheaterLights.java" |
| 183 | +class TheaterLights { |
| 184 | + public void dim(int level) { |
| 185 | + System.out.println("Theater Ceiling Lights dimming to " + level + "%"); |
| 186 | + } |
| 187 | + |
| 188 | + public void on() { |
| 189 | + System.out.println("Theater Ceiling Lights on"); |
| 190 | + } |
| 191 | +} |
| 192 | +``` |
| 193 | + |
| 194 | +The `TheaterLights` class controls lighting. It can dim lights for movie ambiance and turn them back on. |
| 195 | + |
| 196 | +```java title="Screen.java" |
| 197 | +class Screen { |
| 198 | + public void down() { |
| 199 | + System.out.println("Theater Screen going down"); |
| 200 | + } |
| 201 | + |
| 202 | + public void up() { |
| 203 | + System.out.println("Theater Screen going up"); |
| 204 | + } |
| 205 | +} |
| 206 | +``` |
| 207 | + |
| 208 | +The `Screen` class represents the projection screen. It can move up and down as needed. |
| 209 | + |
| 210 | +```java title="PopcornPopper.java" |
| 211 | +class PopcornPopper { |
| 212 | + public void on() { |
| 213 | + System.out.println("Popcorn Popper on"); |
| 214 | + } |
| 215 | + |
| 216 | + public void off() { |
| 217 | + System.out.println("Popcorn Popper off"); |
| 218 | + } |
| 219 | + |
| 220 | + public void pop() { |
| 221 | + System.out.println("Popcorn Popper popping popcorn!"); |
| 222 | + } |
| 223 | +} |
| 224 | +``` |
| 225 | + |
| 226 | +The `PopcornPopper` provides the fun element for the home theater by popping popcorn. |
| 227 | + |
| 228 | +```java title="HomeTheaterFacade.java" |
| 229 | +class HomeTheaterFacade { |
| 230 | + private Amplifier amp; |
| 231 | + private Tuner tuner; |
| 232 | + private DvdPlayer dvd; |
| 233 | + private Projector projector; |
| 234 | + private Screen screen; |
| 235 | + private TheaterLights lights; |
| 236 | + private PopcornPopper popper; |
| 237 | + |
| 238 | + public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvd, Projector projector, Screen screen, |
| 239 | + TheaterLights lights, PopcornPopper popper) { |
| 240 | + this.amp = amp; |
| 241 | + this.tuner = tuner; |
| 242 | + this.dvd = dvd; |
| 243 | + this.projector = projector; |
| 244 | + this.screen = screen; |
| 245 | + this.lights = lights; |
| 246 | + this.popper = popper; |
| 247 | + } |
| 248 | + |
| 249 | + // High‑level operation |
| 250 | + public void watchMovie(String movie) { |
| 251 | + System.out.println("Get ready to watch a movie..."); |
| 252 | + popper.on(); |
| 253 | + popper.pop(); |
| 254 | + lights.dim(10); |
| 255 | + screen.down(); |
| 256 | + projector.on(); |
| 257 | + projector.wideScreenMode(); |
| 258 | + amp.on(); |
| 259 | + amp.setDvd(); |
| 260 | + amp.setSurroundSound(); |
| 261 | + amp.setVolume(5); |
| 262 | + dvd.on(); |
| 263 | + dvd.play(movie); |
| 264 | + } |
| 265 | + |
| 266 | + // High‑level teardown |
| 267 | + public void endMovie() { |
| 268 | + System.out.println("Shutting movie theater down..."); |
| 269 | + popper.off(); |
| 270 | + lights.on(); |
| 271 | + screen.up(); |
| 272 | + projector.off(); |
| 273 | + amp.off(); |
| 274 | + dvd.stop(); |
| 275 | + dvd.eject(); |
| 276 | + dvd.off(); |
| 277 | + } |
| 278 | +} |
| 279 | +``` |
| 280 | + |
| 281 | +The `HomeTheaterFacade` class is the main facade. It simplifies the process by combining all subsystem operations into two simple methods: `watchMovie()` and `endMovie()`. This reduces complexity for the user. |
| 282 | + |
| 283 | +```java title="FacadePattern.java" |
| 284 | +public static void main(String[] args) { |
| 285 | + // Instantiate all components |
| 286 | + Amplifier amp = new Amplifier(); |
| 287 | + Tuner tuner = new Tuner(); |
| 288 | + DvdPlayer dvd = new DvdPlayer(); |
| 289 | + Projector projector = new Projector(); |
| 290 | + Screen screen = new Screen(); |
| 291 | + TheaterLights lights = new TheaterLights(); |
| 292 | + PopcornPopper popper = new PopcornPopper(); |
| 293 | + |
| 294 | + // Create facade |
| 295 | + HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvd, projector, screen, lights, popper); |
| 296 | + |
| 297 | + // Use facade to simplify operations |
| 298 | + homeTheater.watchMovie("Inception"); |
| 299 | + System.out.println(); |
| 300 | + homeTheater.endMovie(); |
| 301 | + } |
| 302 | +``` |
| 303 | +_Output_: |
| 304 | + |
| 305 | +```text |
| 306 | +Get ready to watch a movie... |
| 307 | +Popcorn Popper on |
| 308 | +Popcorn Popper popping popcorn! |
| 309 | +Theater Ceiling Lights dimming to 10% |
| 310 | +Theater Screen going down |
| 311 | +Projector on |
| 312 | +Projector in widescreen mode |
| 313 | +Amplifier on |
| 314 | +Amplifier setting DVD input |
| 315 | +Amplifier surround sound on |
| 316 | +Amplifier volume set to 5 |
| 317 | +DVD Player on |
| 318 | +DVD Player playing "Inception" |
| 319 | +
|
| 320 | +Shutting movie theater down... |
| 321 | +Popcorn Popper off |
| 322 | +Theater Ceiling Lights on |
| 323 | +Theater Screen going up |
| 324 | +Projector off |
| 325 | +Amplifier off |
| 326 | +DVD Player stopped |
| 327 | +DVD Player eject |
| 328 | +DVD Player off |
| 329 | +``` |
| 330 | + |
| 331 | +--- |
| 332 | +## Design Principles: |
| 333 | + |
| 334 | +- **Encapsulate What Varies** - Identify the parts of the code that are going to change and encapsulate them into separate class just like the Strategy Pattern. |
| 335 | +- **Favor Composition Over Inheritance** - Instead of using inheritance on extending functionality, rather use composition by delegating behavior to other objects. |
| 336 | +- **Program to Interface not Implementations** - Write code that depends on Abstractions or Interfaces rather than Concrete Classes. |
| 337 | +- **Strive for Loosely coupled design between objects that interact** - When implementing a class, avoid tightly coupled classes. Instead, use loosely coupled objects by leveraging abstractions and interfaces. This approach ensures that the class does not heavily depend on other classes. |
| 338 | +- **Classes Should be Open for Extension But closed for Modification** - Design your classes so you can extend their behavior without altering their existing, stable code. |
| 339 | +- **Depend on Abstractions, Do not depend on concrete class** - Rely on interfaces or abstract types instead of concrete classes so you can swap implementations without altering client code. |
| 340 | +- **Talk Only To Your Friends** - An object may only call methods on itself, its direct components, parameters passed in, or objects it creates. |
| 341 | + |
0 commit comments