Table of Contents
Facade Pattern
Το Facade Pattern (Μοτίβο Πρόσοψης) ανήκει στα Structural Design Patterns (Δομικά Μοτίβα Σχεδιασμού). Ο κύριος στόχος του είναι να παρέχει μια απλή, ενιαία και εύχρηστη διεπαφή (interface) απέναντι σε ένα περίπλοκο σύστημα από κλάσεις ή API. Φανταστείτε το Facade σαν ένα υπάλληλο υποδοχής ξενοδοχείου, που αντί να μεριμνείτε εσείς για φαγητό, καθαρά σεντόνια ή ταξί, μιλάτε απευθείας μόνο με τον υπάλληλο αυτόν και εκείνος αναλαμβάνει να συντονίσει όλες τις εκκρεμότητες.
Παράδειγμα - Home Theater Automation Service
Ας υποθέσουμε ότι θέλετε να φτιάξετε ένα Home Theater. Για να δείτε μια ταινία, πρέπει χειροκίνητα να:
- Nα χαμηλώσετε τα φώτα.
- Να ενεργοποιήσετε τον προβολέα (Projector).
- Να ενεργοποιήσετε το ηχοσύστημα (Sound System) και να ρυθμίσετε την ένταση.
- Να ξεκινήσετε την αναπαραγωγή της ταινίας.
Αντί ο Client να καλεί πολλές διαφορετικές μεθόδους, θα φτιάξουμε ένα HomeTheaterFacade για τη διαχείριση του Home Theater.
- TheaterLights.java
// 1. Το σύστημα φωτισμού class TheaterLights { public void on() { System.out.println("Τα φώτα του δωματίου άναψαν."); } public void dim(int level) { System.out.println("Τα φώτα χαμήλωσαν στο " + level + "%."); } }
- Projector.java
// 2. Ο προβολέας class Projector { public void on() { System.out.println("Ο προβολέας ενεργοποιήθηκε."); } public void off() { System.out.println("Ο προβολέας απενεργοποιήθηκε."); } public void wideScreenMode() { System.out.println("Ο προβολέας ρυθμίστηκε σε widescreen (16:9)."); } }
- SoundSystem.java
// 3. Το ηχοσύστημα class SoundSystem { public void on() { System.out.println("Το ηχοσύστημα ενεργοποιήθηκε."); } public void off() { System.out.println("Το ηχοσύστημα απενεργοποιήθηκε."); } public void setVolume(int level) { System.out.println("Η ένταση του ήχου ρυθμίστηκε στο " + level + "."); } }
- StreamingPlayer.java
// 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 που λειτουργεί ως πρόσοψη στο περίπλοκο σύστημα ρυθμίσεων που περιγράψαμε.
- HomeTheaterFacade.java
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, καθώς δε χρειάζται να έχει καμία γνώση για το πως λειτουργεί εσωτερικά το σύστημα.
- HomeTheaterUser.java
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 και να ρυθμίσει χειροκίνητα μόνο τα φώτα, έχει τη δυνατότητα να το κάνει.
