Facade (Homlokzat)
Kategória: Strukturális minta (Structural Pattern)
Lényege és célja
A Facade minta célja, hogy egy komplex, sok osztályból álló alrendszer (subsystem) elé egy egyszerű, letisztult, és egységes interfészt (homlokzatot) húzzon fel.
Ahelyett, hogy a kliens kódnak ismernie kellene a motorháztető alatt lévő összes apró alkatrészt és azok helyes hívási sorrendjét, a kliens csak a Facade-del kommunikál. A Facade fogadja az egyszerű kéréseket, majd a háttérben "levezényli" a bonyolult műveletsort.
Analógia a való életből
Gondolj egy éttermi rendelésre! Te (a kliens) csak a pincérrel (a Facade) beszélsz. Azt mondod: "Kérek egy sajtburgert menüben". Nem kell lemenned a konyhába a szakácshoz, nem kell szólnod a raktárosnak a krumpliért, és nem kell elmagyaráznod a kasszásnak, hogyan blokkolja be. A pincér az egyetlen belépési pontod, aki elintézi a komplex alrendszerek (konyha, raktár, kassza) összehangolását.
Mikor használjuk?
- Amikor egy nagyon komplex vagy rosszul megírt (legacy) alrendszert kell használnunk, és el akarjuk rejteni annak bonyolultságát a saját letisztult kliens kódunk elől.
- Amikor csökkenteni akarjuk a csatolást (coupling) a kliens és az alrendszer osztályai között. Ha a háttérben megváltozik egy alrendszer logikája, elég csak a Facade osztályt frissíteni, a kliens kód érintetlen marad.
- Amikor a rendszert rétegekre (layers) akarjuk bontani, és minden rétegnek csak a saját Facade-ján keresztül adunk hozzáférést a többi réteghez.
Mermaid Diagram
A diagramon jól látható, hogy a kliens (Main) mentesül a függőségektől: nem kell ismernie sem a TV-t, sem a lámpákat, sem a klímát. Csak a SmartHomeFacade-ot ismeri, ami "HAS-A" (kompozíció) kapcsolatban áll az alrendszerekkel.
classDiagram
class Client
class SmartHomeFacade {
-tv: Tv
-lights: Lights
-airConditioner: AirConditioner
+SmartHomeFacade(ac, tv, lights)
+startMovieMode() void
+stopMovieMode() void
}
%% Alrendszerek
class Tv {
+turnOn() void
+turnOff() void
}
class Lights {
+dim() void
+brighten() void
}
class AirConditioner {
+setTemperature(degrees: int) void
+turnOff() void
}
Client --> SmartHomeFacade : "csak ezt használja"
SmartHomeFacade --> Tv : "vezérli"
SmartHomeFacade --> Lights : "vezérli"
SmartHomeFacade --> AirConditioner : "vezérli"
note for Client "Egy gombnyomás a kliensnél\nkomplex logikát indít el a háttérben." Forráskód
package structural.facade;
class Tv {
void turnOn() {
System.out.println("Tv bekapcsolva.");
}
void turnOff() {
System.out.println("Tv kikapcsolva");
}
}
class Lights {
void dim() {
System.out.println("Fények halványítva");
}
void brighten() {
System.out.println("Fények fényesítve");
}
}
class AirConditioner {
void setTemperature(int degrees) {
System.out.printf("Hőmérséklet beállítva: %s\n", degrees);
}
void turnOff() {
System.out.println("Légkondi kikapcsolva");
}
}
class SmartHomeFacade {
private final AirConditioner airConditioner;
private final Tv tv;
private final Lights lights;
SmartHomeFacade(AirConditioner airConditioner, Tv tv, Lights lights) {
this.airConditioner = airConditioner;
this.tv = tv;
this.lights = lights;
}
void startMovieMode() {
tv.turnOn();
lights.dim();
airConditioner.setTemperature(22);
}
void stopMovieMode() {
tv.turnOff();
lights.brighten();
airConditioner.turnOff();
}
}
class Main {
static void main() {
var smartHomeFacade = new SmartHomeFacade(
new AirConditioner(),
new Tv(),
new Lights()
);
smartHomeFacade.startMovieMode();
System.out.println("After the movie");
smartHomeFacade.stopMovieMode();
}
}