====== Facade Pattern ======
Το Facade Pattern (Μοτίβο Πρόσοψης) ανήκει στα Structural Design Patterns (Δομικά Μοτίβα Σχεδιασμού). Ο κύριος στόχος του είναι να παρέχει μια απλή, ενιαία και εύχρηστη διεπαφή (interface) απέναντι σε ένα περίπλοκο σύστημα από κλάσεις ή API. Φανταστείτε το Facade σαν ένα υπάλληλο υποδοχής ξενοδοχείου, που αντί να μεριμνείτε εσείς για φαγητό, καθαρά σεντόνια ή ταξί, μιλάτε απευθείας μόνο με τον υπάλληλο αυτόν και εκείνος αναλαμβάνει να συντονίσει όλες τις εκκρεμότητες.
===== Παράδειγμα - Home Theater Automation Service =====
Ας υποθέσουμε ότι θέλετε να φτιάξετε ένα Home Theater. Για να δείτε μια ταινία, πρέπει χειροκίνητα να:
* Nα χαμηλώσετε τα φώτα.
* Να ενεργοποιήσετε τον προβολέα (Projector).
* Να ενεργοποιήσετε το ηχοσύστημα (Sound System) και να ρυθμίσετε την ένταση.
* Να ξεκινήσετε την αναπαραγωγή της ταινίας.
Αντί ο Client να καλεί πολλές διαφορετικές μεθόδους, θα φτιάξουμε ένα HomeTheaterFacade για τη διαχείριση του Home Theater.
// 1. Το σύστημα φωτισμού
class TheaterLights {
public void on() { System.out.println("Τα φώτα του δωματίου άναψαν."); }
public void dim(int level) { System.out.println("Τα φώτα χαμήλωσαν στο " + level + "%."); }
}
// 2. Ο προβολέας
class Projector {
public void on() { System.out.println("Ο προβολέας ενεργοποιήθηκε."); }
public void off() { System.out.println("Ο προβολέας απενεργοποιήθηκε."); }
public void wideScreenMode() { System.out.println("Ο προβολέας ρυθμίστηκε σε widescreen (16:9)."); }
}
// 3. Το ηχοσύστημα
class SoundSystem {
public void on() { System.out.println("Το ηχοσύστημα ενεργοποιήθηκε."); }
public void off() { System.out.println("Το ηχοσύστημα απενεργοποιήθηκε."); }
public void setVolume(int level) { System.out.println("Η ένταση του ήχου ρυθμίστηκε στο " + level + "."); }
}
// 4. Η πηγή της ταινίας (π.χ. Streaming Service)
class StreamingPlayer {
public void on() { System.out.println("Η συσκευή αναπαραγωγής ενεργοποιήθηκε."); }
public void play(String movie) { System.out.println("Αναπαραγωγή της ταινίας: '" + movie + "'"); }
public void stop() { System.out.println("Η ταινία σταμάτησε."); }
public void off() { System.out.println("Η συσκευή αναπαραγωγής απενεργοποιήθηκε."); }
}
Θα δημιουργήσουμε την κλάση ''Facade'' που λειτουργεί ως πρόσοψη στο περίπλοκο σύστημα ρυθμίσεων που περιγράψαμε.
public class HomeTheaterFacade {
private TheaterLights lights;
private Projector projector;
private SoundSystem sound;
private StreamingPlayer player;
// Ο Constructor δέχεται τα αντικείμενα του υποσυστήματος
public HomeTheaterFacade(TheaterLights lights, Projector projector, SoundSystem sound, StreamingPlayer player) {
this.lights = lights;
this.projector = projector;
this.sound = sound;
this.player = player;
}
// Απλοποιημένη μέθοδος για την εκκίνηση της ταινίας
public void watchMovie(String movie) {
System.out.println("\n--- Getting ready for the movie... ---");
lights.dim(10);
projector.on();
projector.wideScreenMode();
sound.on();
sound.setVolume(20);
player.on();
player.play(movie);
System.out.println("--- Movie Started! ---\n");
}
// Απλοποιημένη μέθοδος για τον τερματισμό
public void endMovie() {
System.out.println("\n--- Shuttting down Home Theater... ---");
lights.on();
projector.off();
sound.off();
player.stop();
player.off();
System.out.println("--- Done. ---\n");
}
}
Δείτε πόσο απλός γίνεται ο κώδικας του πελάτη που χρησιμοποιεί την κλάση ''HomeTheaterFacade'', καθώς δε χρειάζται να έχει καμία γνώση για το πως λειτουργεί εσωτερικά το σύστημα.
public class HomeTheaterUser {
public static void main(String[] args) {
// Δημιουργία των εξαρτημάτων του υποσυστήματος
TheaterLights lights = new TheaterLights();
Projector projector = new Projector();
SoundSystem sound = new SoundSystem();
StreamingPlayer player = new StreamingPlayer();
// Δημιουργία της πρόσοψης
HomeTheaterFacade homeTheater = new HomeTheaterFacade(lights, projector, sound, player);
// Ο χρήστης με μία μόνο εντολή ξεκινάει την ταινία
homeTheater.watchMovie("Inception");
// ... περνάει η ώρα και τελειώνει η ταινία ...
// Ο χρήστης κλείνει τα πάντα με μία εντολή
homeTheater.endMovie();
}
}
==== Πλεονεκτήματα: ====
* **Μείωση Πολυπλοκότητας:** Απομονώνει τον Client από τα πολύπλοκα υποσυστήματα.
* **Χαλαρή Σύζευξη (Loose Coupling):** Αν αύριο αλλάξει ο τρόπος που λειτουργεί το SoundSystem, θα χρειαστεί να αλλάξει μόνο η κλάση Facade και όχι ολόκληρη η εφαρμογή μας.
* **Ευκολία στη χρήση:** Ιδανικό όταν ενσωματώνουμε μεγάλες, κακογραμμένες ή παλιές (legacy) βιβλιοθήκες τρίτων.
💡 **Σημείωση:** Το Facade Pattern δεν κρύβει απαγορευτικά το υποσύστημα. Αν ένας Client θέλει να προσπεράσει το HomeTheaterFacade και να ρυθμίσει χειροκίνητα μόνο τα φώτα, έχει τη δυνατότητα να το κάνει.